Eu passo 1
(stdout)/ 2
(stderr) para a read
chamada do sistema, mas ainda funciona bem. Então eu passo 0
(stdin) para a write
chamada do sistema e descubro que funciona também!
int main(int argc, char** argv){
char buf[1024] = "abcdefghi\n";
write(0, buf, 10);
char readbuf[1024] = {0};
// read(1, readbuf, 10); works too
read(2, readbuf, 10);
write(2, readbuf, 10);
return 0;
}
resultado:
abcdefghi
hey stdin <-- I input this
hey stdin
Confuso, pensei que deveria ser um erro.
Experiência:
Então eu tentei redirecionar fd 2.
$ ./a.out 2>/dev/null
desta vez, tanto a leitura quanto a segunda gravação não são 'visíveis'. A saída é
abcdefgi
Então o stderr pode ser usado para leitura?
Eu então fecho o stdout & stderr e faço duas cópias do stdin:
int main(int argc, char** argv){
char buf[1024] = "abcdefghi\n";
close(1);
close(2);
dup2(0, 1);
dup2(0, 2);
write(0, buf, 10);
char redbuf[1024] = {0};
read(2, redbuf, 10);
write(2, redbuf, 10);
return 0;
}
Novamente funciona.
resultado:
abcdefghi
hey stdin <-- I input this
hey stdin
Então stdin pode ser usado para escrever?
Preciso de uma explicação aqui.
Pergunta
Eu quero saber:
Por que stdout/stderr pode ser usado para leitura?
Por que stdin pode ser usado para gravação?
Os três fluxos ( stdin,stdout,stderr ) são internamente um fluxo?
Se não, por que estou obtendo esse resultado?
É apenas convenção usar fd 0/1/2 para entrada/saída/erro. Se você chamar um programa sem redirecionamento, todos os três se referem ao seu tty e seu tty é aberto com acesso de leitura e gravação. Isso significa que você pode ler ou escrever para eles como quiser. Você pode chamá-los de mesmo fluxo, embora o fluxo de expressão seja frequentemente usado para E/S de nível mais alto, como
FILE
em C oustream
em C++.Esta é a razão pela qual ambos os exemplos redirecionados ou não apenas ecoam o texto que você digita.
Por outro lado, se você fizer o redirecionamento, o shell abrirá os arquivos com acesso somente leitura ou somente gravação. No seu exemplo
./a.out 2>/dev/null
, o write to0
ainda está conectado ao terminal porque não é redirecionado e, portanto, é exibido na tela. A leitura de2
está conectada apenas a uma gravação/dev/null
e, portanto, deve falhar, mas você não notaria a diferença do seu programa. A gravação para é bem-2
sucedida, mas é gravada para/dev/null
. A leitura inválida e a gravação válida/dev/null
não são visíveis no seu terminal.Desde que você não tenha redirecionado stdin/stdout/stderr, esses descritores de arquivo foram abertos pelo procedimento de login e isso abre o relacionado
tty
para leitura e gravação como o primeiro arquivo (resultando no descritor de arquivo #0) e depois chamadup()
2 vezes para obter os descritores de arquivo para stdout e stderr.Como mencionado em Como `less` pega dados de stdin enquanto ainda consegue ler comandos do usuário? em tempos antigos (antes
/dev/tty
de ter sido apresentado aUNIX
) programas comomore
o did readstderr
quando pedia confirmação.