读取过程中的Unix / Linux管道行为在写入过程之前终止

我有这个:

$ ls -lh file -rw-r--r-- 1 ankur root 181M Sep 23 20:09 file $ head -6 file z abc abc abc abc abc $ cat file | grep -m 1 z z 

题:

为什么最后一行中的cat命令行没有过早地使用SIGPIPE死亡? 我认为这应该发生,因为grep终止与cat file相比,没有时间终止。 随着阅读过程的消失, cat将尝试写入破损的管道并且应该用SIGPIPE死掉。

更新:

我最后写了这个:readstdin.c

 # include  # include  int main() { ssize_t n ; char a[5]; n = read(0, a, 3); printf("read %zd bytes\n", n); return(0); } 

我这样使用它:

 $ cat file | ./readstdin $ yes | ./readstdin 

但仍然cat或是不会过早死亡。 我期待它,因为通过读取过程在写入过程完成写入之前终止。

如果某个管道(2)的读取端接近(2) -ed,则进一步写入(2)将得到SIGPIPE 信号(7) 。 另请阅读管道(7) 。

当管道缓冲区变满时,它们将获得SIGPIPE

yes | ./readstdin yes | ./readstdin命令, yes命令获得一个SIGPIPE信号。 只是在终端中尝试yes ,它会无限期地吐出一些输出,直到你杀了它为止。

cat file | ./readstdin cat file | ./readstdin命令,它可能发生(特别是如果file很小,少于sysconf(_POSIX_PIPE_BUF)字节,可能是4096字节), cat命令close(2) STDOUT_FILENO描述符和管道是仍然不满。 然后cat可能不会得到任何SIGPIPE

正常进程关闭输入流,导致SIGPIPE。 在手册页中,它提到-m停止读取,并“确保标准输入位于退出之前的最后一个匹配行之后”。 所以它实际上并没有关闭流。 你可以这样certificate:

 cat file | (grep -m1 z && grep -m1 c) 

你会得到第一个z之后的第一个c ,这有时是有用的。 在最后一个grep退出之后,没有流可以去的地方,所以它未被读取并且整组命令退出。 你可以certificate:

 (while true; do echo z; sleep 1; done) | grep -m3 z (while true; do echo z; sleep 1; done) | grep --line-buffered z | head -3