[英]Unix/Linux pipe behavior when reading process terminates before writing process
我有这个:
$ 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过早死亡? 我认为这应该发生,因为与183MB的cat file
相比, grep
终止。 随着读取过程的消失, cat
将尝试写入损坏的管道,并且应该因SIGPIPE而死。
更新:
我最终写了这个:readstdin.c
# include <unistd.h>
# include <stdio.h>
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
或者yes
不过早死亡。 我希望这样做是因为在编写过程完成之前,阅读过程终止了。
如果某些pipe(2)的读取端是close(2) -ed,则进一步的write(2)将获得SIGPIPE
signal(7) 。 另请阅读pipe(7) 。
当管道缓冲区已满时,他们将获得SIGPIPE
。
在yes | ./readstdin
yes | ./readstdin
命令, yes
命令会收到SIGPIPE
信号。 只需在终端上尝试yes
,它会无限期地吐出一些输出,直到您将其杀死为止。
在cat file | ./readstdin
cat file | ./readstdin
命令,它会发生(尤其是如果file
非常小,小于sysconf(_POSIX_PIPE_BUF)
字节,这可能是4096个字节),该cat
命令是close(2)
-ing的STDOUT_FILENO
描述符和该管还不满。 那么cat
可能不会得到任何SIGPIPE
。
正常进程会关闭输入流,从而导致SIGPIPE。 在手册页中,它提到-m
停止读取,并且“确保标准输入位于退出之前的最后一个匹配行之后”。 因此,它实际上并没有关闭流。 您可以这样演示:
cat file | (grep -m1 z && grep -m1 c)
您会在第一个z
之后获得第一个c
,这有时很有用。 在最后一个grep退出之后,该流就没有空间了,因此它保持未读状态,并且整个命令组都退出了。 您可以演示:
(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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.