將“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

相關內容