为什么不yes | head
挂?
我认为系统会收集所有结果yes
,然后将其通过管道传输到head
,并且由于yes
是无限循环,因此系统挂起。但是,它实际上可以停止并显示 10 行y
.
收集数据完成后系统如何停止yes
?head
当您说yes | head
外壳将安排事情时,输出yes
进入管道,输入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 +++
系统从 yes 收集所有结果,然后将其通过管道传送到 head
那将是非常低效的。当您使用管道时,操作系统会为管道通信创建一个缓冲区。
send | receive
只要缓冲区中有足够的空间,发送进程就会写入其中,如果缓冲区中有足够的数据,接收者就会处理它。如果没有等待进程被阻塞。
一旦head
完成,操作系统就会注意到它已终止,它将触发一个信号 ( SIGPIPE
),该信号将终止发送进程(除非进程处理它)。