将“yes”传递给另一个命令时会发生什么?

将“yes”传递给另一个命令时会发生什么?

如果yes命令连续回显“y”直到被杀死,那么它永远不会完成,对吗?如果它永远不会完成那么它如何将其输出传递到下一个命令?

答案1

yes程序将与读取器同时写入管道。如果管道为空,则读取器将在内核调用中阻塞以read()等待更多输入。如果管道已满,则写入将在内核中阻塞,以等待write()读取器释放管道中的一些空间。

SIGPIPE如果进程要写入没有读取器的管道,则内核会向该进程发送一个信号。当读取进程关闭管道的读取端时(无论是明确的还是由于其终止),下次写入进程尝试写入管道时,它将收到信号SIGPIPE

为了说明这一点,请考虑这个yes打印连续流的程序的简化版本y。该程序的不同之处在于yes,它在收到SIGPIPE信号时生成一条消息:

#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;
}

我可以编译并运行该程序并看到它的行为如下yes

$ gcc ex.c -o myes

$ ./myes
y
y
y
...

如果我将输出通过管道传输到另一个进程,当该进程终止(并且管道的读取端关闭)时,程序myes会收到SIGPIPE信号(如相关消息所示)。

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

相关内容