读取过程中的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