0

我有这个:

$ 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 的文件grep相比,它会立即终止。cat file随着读取过程的消失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

但仍然catyes不会过早死亡。我希望它是因为阅读过程在写入过程完成写入之前终止。

4

2 回答 2

2

如果某个pipe(2)的读取端是close(2) -ed,则进一步的write(2)将得到一个SIGPIPE signal(7)。另请阅读pipe(7)

SIGPIPE当管道缓冲区变满时,他们会得到。

yes | ./readstdin命令中,yes命令得到 aaSIGPIPE信号。只需yes在终端中尝试,它会无限期地吐出一些输出,直到你杀死它。

cat file | ./readstdin命令中,它可能会发生(特别是如果file它非常小,小于那个sysconf(_POSIX_PIPE_BUF)字节,可能是 4096 字节),该cat命令正在close(2)-ingSTDOUT_FILENO描述符并且管道仍未满。那么cat可能什么也得不到SIGPIPE

于 2013-09-24T05:04:17.680 回答
1

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

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

你会在第一个c之后得到第一个z,这有时很有用。在最后一个 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
于 2013-09-24T03:57:56.833 回答