为什么yes | head
没有挂起?
我认为系统会从yes
收集所有结果,然后将其传递给head
,并且由于yes
是一个无限循环,系统会挂起。但是,它实际上可以停止并显示10行y
。
当yes
收集数据时,系统如何设法停止head
?
答案 0 :(得分:5)
当你说yes | head
时,shell会安排一些内容,使yes
的输出转到pipe,head
的输入来自同一个管道。当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
),它将终止发送过程(除非进程处理它)。