O que acontece ao canalizar o `sim` para outro comando?

O que acontece ao canalizar o `sim` para outro comando?

Se o yescomando ecoar "y" continuamente até ser morto, isso nunca será feito, certo? Se isso nunca for feito, como ele canaliza a saída para o próximo comando?

Responder1

O yesprograma irá escrever no pipe, simultaneamente com o leitor. Se o pipe estiver vazio, o leitor bloqueará o kernel em uma chamada para read()aguardar mais entradas. Se o canal estiver cheio, a gravação será bloqueada no kernel em uma chamada para write()aguardar que o leitor libere espaço no canal.

O kernel fornece um SIGPIPEsinal para um processo se ele estiver vinculado à gravação em um canal que não possui leitor. Quando o processo de leitura fecha a extremidade de leitura do tubo (explicitamente ou como resultado de seu término), na próxima vez que o processo de escrita tentar escrever no tubo, ele receberá o SIGPIPEsinal.

Para ilustrar este ponto, considere esta versão simplificada do yesprograma que imprime um fluxo contínuo de y. Este programa difere yesporque gera uma mensagem ao receber o SIGPIPEsinal:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

static void handler(int sig) {
    #define msg "received SIGPIPE signal, terminating\n"
    write(2, msg, sizeof msg);
    exit(1);
    #undef msg
}

int main(void) {
    // Instruct the kernel to call the handler() function when
    // this process receives the SIGPIPE signal.  The default behavior
    // when this signal is received is for the process to terminate.
    signal(SIGPIPE, handler);

    for (;;) {
        if (write(1, "y\n", 2) < 0) {
            fprintf(stderr, "%s\n", strerror(errno));
            return 2;
        }
    }
    return 0;
}

Posso compilar e executar o programa e ver se ele se comporta como yes:

$ gcc ex.c -o myes

$ ./myes
y
y
y
...

Se eu canalizar a saída para outro processo, quando esse processo terminar (e a extremidade de leitura do canal for fechada), o myesprograma receberá o SIGPIPEsinal (conforme indicado pela mensagem associada).

$ ./myes | head -n5
y
y
y
y
y
received SIGPIPE signal, terminating

informação relacionada