为什么“是|头”不挂?

时间:2014-01-25 12:36:33

标签: unix pipe unix-head

为什么yes | head没有挂起?

我认为系统会从yes收集所有结果,然后将其传递给head,并且由于yes是一个无限循环,系统会挂起。但是,它实际上可以停止并显示10行y

yes收集数据时,系统如何设法停止head

2 个答案:

答案 0 :(得分:5)

当你说yes | head时,shell会安排一些内容,使yes的输出转到pipehead的输入来自同一个管道。当head读取10行时,它会关闭其STDIN_FILENO,从而关闭其管道末端。当yes尝试写入已关闭的管道时,会获得SIGPIPE,其默认操作是将其删除。

测试此方法的一种简单方法是使用strace

$ strace yes | head
y
[...]
y
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 4096) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=4069, si_uid=1000} ---
+++ killed by SIGPIPE +++

答案 1 :(得分:4)

  

系统从yes收集所有结果,然后将其传递给头

那将是非常低效的。使用管道时,操作系统会为管道通信创建缓冲区。

send | receive

只要缓冲区中有足够的空间,发送过程就会在其中写入,如果缓冲区中有足够的数据,接收方将处理它。如果没有等待进程被阻止。

一旦head完成,操作系统就会注意到它终止,它将触发一个信号(SIGPIPE),它将终止发送过程(除非进程处理它)。