如果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