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