Uma extremidade de um pipe lê e grava fd?

4
Até onde eu entendi uma ponta de um cano tem tanto ler quanto escrever fd's e a outra ponta também leu e escreveu fd's. É por isso que quando estamos escrevendo usando fd[1] , estamos fechando o final de leitura, por exemplo, fd[0] do mesmo lado do pipe e quando estamos lendo a segunda extremidade usando fd[0] , fechamos fd[1] desse final. Estou correcto?

    
por Subi Suresh 29.03.2013 / 18:41

3 respostas

6

Sim, um pipe feito com pipe () possui dois descritores de arquivo. fd[0] para leitura e fd[1] para escrita.

Não, você não precisa fechar nenhuma das extremidades do pipe, ele pode ser usado para comunicação bidirecional.

Editar: nos comentários você quer saber como isso se relaciona com ls | less , então vou explicar isso também:

Seu shell tem três descritores de arquivos abertos: 0 (stdin), 1 (stdout) e 2 (stderr). Quando um shell executa um comando, ele faz algo assim (simplifiquei um pouco:

pid = fork();
if(pid == 0) {
    /* I am the child */
    execve(...); /* Whatever the user asked for */
}
else {
    waitpid(pid); /* Wait for child to complete */
}

Os descritores de arquivo 0, 1 e 2 são herdados pelo filho, portanto, a entrada / saída funciona conforme o esperado. Se você faz ls | pipe , algo ligeiramente diferente acontece para fazer o redirecionamento:

int pipe[2];
pipe(pipe, 0);

pid1 = fork();
if(pid1 == 0) {
    /* This is ls, we need to remap stdout to the pipe. We don't care about reading from the pipe */
    close(pipe[0]);
    close(1);
    dup2(pipe[1], 1);
    execve(...);
}
else {
    pid2 = fork();
    if(pid2 == 0) {
        /* This is less, it reads from the pipe */
        close(pipe[1]);
        close(0);
        dup2(pipe[0], 0);
        execve(...);
    }
    else {
        waitpid(pid1);
        waitpid(pid2);
    }
}

Assim, o shell cria o pipe, os garfos e, pouco antes de executá-lo, remapeia o pipe para stdin ou stdout dos processos filhos, fazendo com que o fluxo de dados seja do processo um para o process 2. Como os shell pipes não são bidirecionais, eles usam uma extremidade do pipe e feche a outra extremidade (ela realmente fecha a outra extremidade também, depois de duplicar o filedescriptor para stdin ou stdout).

    
por 29.03.2013 / 18:55
4

Este é um resumo da conversa por chat Dennis e eu tive, simplificado para que até mesmo outros novatos possam usá-lo. Ao executar ls | less :

  1. O shell bash é o processo pai que tem fd[0] , fd[1] e fd[2] .
  2. pipe() é chamado pelo pai e cria um canal que nada mais é do que um buffer para acomodar dados, e possui um descritor de arquivo em cada extremidade, um para leitura e outro para gravação.
  3. O processo filho herda todos os fds abertos; 0, 1 e 2, bem como os dois para o tubo. Assim, ls tem sua própria cópia do buffer com fd[0] e fd[1] , mas ambos apontam para o mesmo pipe fds de bash . Dentro do primeiro processo filho, ls é executado e agora precisamos remapear a saída para a extremidade de gravação do canal ( fd[1] ) e depois para o console. Então, close(1) e dup(fd[1]) farão o remapeamento. close(1) afeta apenas o processo filho ls , não o bash pai. Agora, a saída de ls será direcionada para a extremidade de gravação fd[1] do canal para o filho. fd[0] ainda é o final da leitura, e não queremos que os dados sejam lidos por ls , então ainda precisamos fechar essa extremidade com close(fd[0]) . Novamente, isso só fecha o descritor de arquivo em ls , não bash .
  4. Novamente, fazemos um fork para tornar o processo filho less , que herda os descritores de arquivos de pipe. A entrada para less precisa ser lida no buffer, portanto, usamos fd[0] . Como fd[0] não é mais stdin, precisamos remapá-lo, então close(0) e dup(fd[0]) . Agora fd[0] apontará para stdin, então a entrada aqui é a saída de ls . less usa fd[0] para ler e fecha o fim da gravação fd[1] as less quer impedir que os dados lidos por sua escrita sejam gravados novamente
por 13.04.2017 / 14:36
-1

você precisa close fd [1] no pai antes de chamar fork() para menos comando caso contrário, o comando less esperará infinitamente pela entrada

    
por 09.09.2013 / 10:34

Tags