【问题标题】:Is it really necessary to close the unused end of the pipe in a process是否真的有必要在进程中关闭未使用的管道端
【发布时间】:2014-09-06 02:37:54
【问题描述】:

我正在阅读 UNIX 中用于 2 个进程之间的进程间通信的管道。我有以下问题

真的有必要关闭未使用的管道末端吗?例如,如果我的父进程正在将数据写入管道而子进程正在从管道中读取,那么是否真的有必要在父进程中关闭管道的读取端并从子进程中关闭写入端?如果我不关闭这些末端,会有任何副作用吗?为什么我们需要关闭这些末端?

【问题讨论】:

  • 我不知道如果有两个读取端是否是未定义的行为,但实际上只有一个从管道读取。

标签: c unix pipe


【解决方案1】:

根据getdtablesize 的手册页

每个进程都有一个固定大小的描述符表,保证 至少有 20 个插槽。

每个管道使用描述符表中的两个条目。关闭管道不需要的一端会释放其中一个描述符。因此,如果您不幸处于每个进程限制为 20 个描述符的系统上,那么您将非常有动力释放不需要的文件描述符。

【讨论】:

  • 一般来说,不关闭文件描述符就像不释放内存一样。您正在占用可能很少见的系统资源。还有一个常见的(软)限制,总文件描述符为 1024 个。
【解决方案2】:

管道注定要用作单向通信渠道。关闭它们是一种很好的做法,可以避免在发送的消息中出现一些混乱。作家的描述符应该对读者关闭,反之亦然。

【讨论】:

    【解决方案3】:

    如果你不这样做,问题就来了。在您的示例中,父级创建了一个用于写入子级的管道。然后它分叉子,但不关闭自己的读取描述符。这意味着管道上仍有两个读取描述符。

    如果子进程只有一个并且它关闭了它(例如,通过退出),父进程会收到一个 SIGPIPE 信号,或者,如果该信号被屏蔽,则会在写入管道时出错。

    但是,管道上有第二个读取描述符(父级的)。现在,如果孩子退出,管道将保持打开状态。父级可以继续写入管道,直到它填满,然后下一次写入将阻塞(如果非阻塞则不写入返回)。

    因此,通过不关闭父级的读取描述符,父级无法检测到子级已关闭其描述符。

    【讨论】:

      【解决方案4】:

      参考here

      引用以上参考:

      [...] 每个管道都提供单向通信;信息从 一个进程到另一个进程。

      为此,父子进程应关闭未使用端 管道。

      关闭未使用的其实还有一个更重要的原因 管道的末端。

      制作读系统时从管道块中读取的进程 调用除非:

      1. 管道包含足够的数据来填充阅读器的缓冲区,或者,
      2. 发送文件结束字符。当每个文件描述符写入结束时,文件结束字符通过管道发送 管道已关闭。任何从管道读取并忘记 关闭管道的写入端将永远被通知 “文件结尾” [...]

      【讨论】:

        猜你喜欢
        • 2018-09-17
        • 1970-01-01
        • 1970-01-01
        • 2014-06-18
        • 1970-01-01
        • 2012-08-03
        • 1970-01-01
        • 1970-01-01
        • 2021-12-08
        相关资源
        最近更新 更多