管道如何知道何时停止

管道如何知道何时停止

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

例如,采用yes(无限输出)head

 yes | head -n 5

它只会产生 5 y

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

答案1

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

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

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


如果您在父 shell 中忽略SIGPIPE,则命令将继承此配置,并且write对损坏的管道的 a 只会errno导致EPIPE.如图所示,yes将此错误字符串化并打印它:

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

相关内容