简体   繁体   English

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

[英]Unix/Linux pipe behavior when reading process terminates before writing process

I have this: 我有这个:

$ 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

Question: 题:

Why is the cat command line in the last line not dying prematurely with SIGPIPE? 为什么最后一行中的cat命令行不会因SIGPIPE过早死亡? I think this should happen because grep terminates in no time compared to cat file that cats 183MB of file. 我认为这应该发生,因为与183MB的cat file相比, grep终止。 With reading process gone cat will try to write to a broken pipe and should die with SIGPIPE. 随着读取过程的消失, cat将尝试写入损坏的管道,并且应该因SIGPIPE而死。

Update: 更新:

I ended up writing this: readstdin.c 我最终写了这个: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);

}

I use it like this: 我这样使用它:

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

But still cat or yes does not die prematurely. 不过还是cat或者yes不过早死亡。 I expect it to because by reading process is terminating before writing process is done writing. 我希望这样做是因为在编写过程完成之前,阅读过程终止了。

If the read end of some pipe(2) is close(2) -ed, further write(2) s will get a SIGPIPE signal(7) . 如果某些pipe(2)的读取端是close(2) -ed,则进一步的write(2)将获得SIGPIPE signal(7) Read also pipe(7) . 另请阅读pipe(7)

They would get the SIGPIPE when the pipe buffer becomes full. 当管道缓冲区已满时,他们将获得SIGPIPE

In the yes | ./readstdin yes | ./readstdin yes | ./readstdin command, the yes command gets aa SIGPIPE signal. yes | ./readstdin命令, yes命令会收到SIGPIPE信号。 Just try yes in a terminal, it spits some output indefinitely ad nauseam till you kill it. 只需在终端上尝试yes ,它会无限期地吐出一些输出,直到您将其杀死为止。

In the cat file | ./readstdin cat file | ./readstdin cat file | ./readstdin command, it could happen (notably if file is quite small, less that sysconf(_POSIX_PIPE_BUF) bytes, which might be 4096 bytes), that the cat command is close(2) -ing the STDOUT_FILENO descriptor and that the pipe is still not full. cat file | ./readstdin命令,它会发生(尤其是如果file非常小,小于sysconf(_POSIX_PIPE_BUF)字节,这可能是4096个字节),该cat命令是close(2) -ing的STDOUT_FILENO描述符和该管还不满。 Then cat may not get any SIGPIPE . 那么cat可能不会得到任何SIGPIPE

Normal processes close the input stream causing a SIGPIPE. 正常进程会关闭输入流,从而导致SIGPIPE。 In the man page, it mentions that -m stops reading, and "ensures that standard input is positioned to just after the last matching line before exiting". 在手册页中,它提到-m停止读取,并且“确保标准输入位于退出之前的最后一个匹配行之后”。 So it doesn't actually close the stream. 因此,它实际上并没有关闭流。 You can demonstrate like this: 您可以这样演示:

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

You'll get the first c after the first z , which is sometimes useful. 您会在第一个z之后获得第一个c ,这有时很有用。 After the last grep exits, there is no place for the stream to go, so it's left unread and the whole group of commands exits. 在最后一个grep退出之后,该流就没有空间了,因此它保持未读状态,并且整个命令组都退出了。 You can demonstrate: 您可以演示:

(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