我正在阅读UNIX中用于两个进程之间进程间通信的管道。我有以下问题
是否真的有必要关闭管道未使用的一端?例如,如果我的父进程正在将数据写入管道并且子进程正在从管道读取,是否真的有必要在父进程中关闭管道的读取端并从子进程关闭写入结束?如果我不接近这些目的,是否有任何副作用?为什么我们需要关闭这些目标?
答案 0 :(得分:12)
如果你不这样做就会出现问题。在您的示例中,父级创建用于写入子级的管道。然后它会分叉子,但不会关闭自己的读取描述符。这意味着管道上仍有两个读取描述符。
如果孩子只有一个并关闭它(例如,通过退出),父母将获得一个SIGPIPE信号,或者如果被屏蔽,则写入管道时会出错。
但是,管道上有第二个读取描述符(父级)。现在,如果孩子退出,管道将保持打开状态。父级可以继续写入管道,直到它填满,然后下一次写入将阻塞(或者如果没有阻塞则返回而不写入。)
因此,通过不关闭父级的读取描述符,父级无法检测到子级已关闭其描述符。
答案 1 :(得分:3)
根据getdtablesize
每个进程都有一个固定大小的描述符表,保证可以使用 至少有20个插槽。
每个管道在描述符表中使用两个条目。关闭不需要的管道末端可释放其中一个描述符。因此,如果您不幸遇到一个系统,其中每个进程限制为20个描述符,那么您将非常积极地释放不需要的文件描述符。
答案 2 :(得分:1)
管道注定要用作单向通信通道。关闭它们是一种很好的做法,可以避免发送消息中的一些混乱。应该为读者关闭Writer的描述符,反之亦然。
答案 3 :(得分:1)
引用here
从以上参考引述:
[...]每个管道都提供单向通信;信息流来自 一个过程到另一个过程。
因此,父进程和子进程应关闭未使用的结尾 的管道。
还有另一个更重要的原因关闭未使用的 管道的末端。
在制作读取系统时从管道块读取过程 致电,除非:
- 管道包含足够的数据以填充读取器的缓冲区,或者
- 文件结束符已发送。当每个文件描述符写入末尾时,文件结尾字符通过管道发送 管道已关闭。从管道读取的任何过程都忘记了 关闭管道的写入端将从不 “文件结束” [...]