Pipe

將“是”傳遞給另一個命令時會發生什麼?

  • March 31, 2020

如果yes命令連續回顯“y”直到被殺死,那麼它永遠不會完成對嗎?如果它永遠不會完成,那麼它如何將它的輸出傳遞給下一個命令?

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

引用自:https://unix.stackexchange.com/questions/576817