passa stdout fd para 'ler' chamada de sistema, mas ainda funciona bem [duplicado]

0

Como o título diz, eu passo 1 (stdout) / 2 (stderr) para read chamada de sistema mas ainda funciona bem. Então eu passo 0 (stdin) para write system call 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;
}

saída:

abcdefghi
hey stdin  <-- I input this
hey stdin

Confuso, achei que deveria ser um erro.

Experiência:

Então tentei redirecionar o fd 2.

$ ./a.out 2>/dev/null

desta vez, tanto a leitura como 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ça duas cópias de 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;
}

Mais uma vez funciona.

saída:

abcdefghi
hey stdin  <-- I input this
hey stdin

Então o stdin pode ser usado para escrever?

Eu preciso de alguma explicação aqui.

Pergunta

Eu quero saber:

Por que o stdout / stderr pode ser usado para leitura?

Por que o stdin pode ser usado para escrever?

O fluxo de três fluxos ( stdin, stdout, stderr ) é internamente ?

Se não, por que estou obtendo esse resultado?

Eu apreciaria se alguém pudesse explicar isso para mim.

    
por Charles 26.08.2018 / 02:43

2 respostas

1

É apenas uma 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ê poderia chamá-los de mesmo fluxo, embora o fluxo de expressão seja frequentemente usado para E / S de nível superior, como FILE em C ou stream em C ++.

Essa é a razão pela qual os exemplos redirecionados ou não apenas refletem o texto digitado.

Por outro lado, se você redirecionar, o shell abrirá os arquivos com acesso somente leitura ou somente gravação. No seu exemplo ./a.out 2>/dev/null , a gravação para 0 ainda está conectada ao terminal porque não é redirecionada e, portanto, é exibida na tela. A leitura de 2 está conectada a uma gravação apenas /dev/null e deve falhar, mas você não notará a diferença do seu programa. A gravação para 2 é bem-sucedida, mas é gravada em /dev/null . A leitura inválida e a gravação válida em /dev/null não estão visíveis no seu terminal.

    
por 26.08.2018 / 09:18
-1

Contanto que você não tenha redirecionado stdin / stdout / stderr, esses arquivos foram abertos pelo procedimento de login e isso abre o tty para leitura e gravação como o primeiro arquivo (resultando no descritor de arquivo # 0) e depois chama dup() 2 vezes para obter os descritores de arquivo para stdout e stderr.

Como mencionado em Como o 'less' pega dados do stdin e ainda consegue ler comandos do usuário? antigamente (antes que o /dev/tty fosse introduzido no UNIX ) programas como more leram stderr ao solicitar confirmação.

    
por 26.08.2018 / 16:06