+1 致Greg Hewgill 引导我的思考过程朝着正确的方向寻找答案。
SIGPIPE 在套接字和管道中的真正原因是过滤器习惯用法/模式适用于 Unix 系统中的典型 I/O。
从管道开始。像 grep 这样的过滤程序通常写入 STDOUT 并从 STDIN 读取,这可能会被 shell 重定向到管道。例如:
cat someVeryBigFile | grep foo | doSomeThingErrorProne
shell 在分叉然后执行这些程序时可能使用dup2 系统调用将STDIN、STDOUT 和STDERR 重定向到适当的管道。
由于过滤器程序grep 不知道也无法知道它的输出已被重定向,因此如果doSomeThingErrorProne 崩溃,告诉它停止写入损坏管道的唯一方法是使用信号写入STDOUT 的返回值很少被检查。
带有套接字的类似物是inetd 服务器代替了外壳。
作为一个例子,我假设您可以将grep 转换为通过TCP 套接字运行的网络服务。例如inetd,如果你想在TCP 8000 端口上拥有一个grep 服务器,那么将其添加到/etc/services:
grep 8000/tcp # grep server
然后将此添加到/etc/inetd.conf:
grep stream tcp nowait root /usr/bin/grep grep foo
将SIGHUP 发送到inetd 并使用telnet 连接到端口8000。这应该会导致inetd 分叉,将套接字复制到STDIN、STDOUT 和STDERR,然后使用 foo 作为参数执行grep。如果您开始在 telnet 中输入行,grep 将回显那些包含 foo 的行。
现在将 telnet 替换为名为 ticker 的程序,例如,该程序将实时股票报价流写入 STDOUT 并在 STDIN 上获取命令。有人远程登录到端口 8000 并键入“start java”以获取 Sun Microsystems 的报价。然后他们起床去吃午饭。 telnet莫名其妙地崩溃了。如果没有要发送的SIGPIPE,那么ticker 会一直发送引号,永远不会知道另一端的进程已经崩溃,并且会不必要地浪费系统资源。