管道如何知道何时停止

Cyr*_*bil 19 pipe

一些程序可以有无限的运行时间并产生无限的输出。当在带有完成命令的管道中使用时,管道如何知道何时停止?

例如,将yes(无限输出)与head

 yes | head -n 5
Run Code Online (Sandbox Code Playgroud)

它只会产生 5 y

结束的第一个命令是停止其他进程输入/输出的命令吗?
它是如何工作的?

PSk*_*cik 24

命令与管道相连(我在这里谈论的是系统原语——显然,它们与 a 相连|)。当管道的读端(stdinof head)变为closed (== 当head显式 ( close) 或隐式 (exit) 关闭它时),尝试写入写端 ( stdoutof yes) 将失败。

默认情况下,这不仅仅是常规errno故障,而是导致写入进程接收到SIGPIPE信号的故障。SIGPIPE 信号的默认处理程序动作是终止。

简而言之——如果你写到一个破损的管道,系统会向你发送 aSIGPIPE并且默认情况下,aSIGPIPE会杀死你。这就是为什么在yes结束时head终止(从而破坏管道)。


如果忽略SIGPIPE父shell,那么该命令将继承这一倾向和write一个破管只会导致errno的错误EPIPE。正如它所显示的那样,yes将此错误字符串化并打印出来:

$ (trap "" SIGPIPE; yes | head -n 5)  
y
y
y
y
yes: standard output: Broken pipe
yes: write error
Run Code Online (Sandbox Code Playgroud)