繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM