【问题标题】:Do we need to close the read end of a pipe explicitly whose write end has already been closed?我们是否需要明确关闭其写端已经关闭的管道的读端?
【发布时间】:2012-08-03 07:35:08
【问题描述】:

我有以下情况。

  1. 我创建了一个管道。

  2. 分叉了一个子进程。

  3. 子进程显式地关闭管道的读取端并写入管道的写入端并退出而不关闭任何东西(exit 应该代表子进程关闭所有打开的文件/管道描述符, 我相信)。

  4. Parent显式地关闭管道的写端并使用fgets从管道的读端读取,直到fgets返回NULL。即它读取完整。

现在我的问题是,为什么父级在完成读取后需要显式关闭管道的读取端?从读取端读取完整数据后,系统完全删除管道不是明智的吗?

我在父项中明确关闭读取端,并且在打开更多管道时迟早会出现Too many file descriptors 错误。我的假设是,一旦管道的写入端关闭并且数据已从读取端完全读取,系统会自动删除管道。因为你不能从管道两次!

那么,一旦数据完全读写结束,系统不删除管道的原因是什么?

【问题讨论】:

  • “因为你不能从管道中两次!”???​​
  • @KerrekSB 我的意思是你可以读取同一个管道两次,但第二次会看到 EOF 对吗?

标签: c pipe fgets inter-process-communicat


【解决方案1】:

您是正确的,一旦孩子退出,系统将关闭管道的写入端。但是,如果子 forks 或将写入端的副本传递给另一个进程,则该管道的另一个写入端可能打开。

系统仍然能够判断管道一端的所有描述符何时已关闭(显式关闭或因为拥有进程退出)。关闭管道另一端的描述符仍然没有意义,因为当父进程试图关闭管道另一端的描述符时,这会导致混乱;要么:

  • fd 已被系统关闭,在这种情况下,当它试图关闭已关闭的 fd 时会出错;或
  • fd 已被重用,更糟糕的是它现在正在关闭一个完全不相关的 fd。

从系统的角度来看,一旦关闭了一端的所有描述符,它很可能已经丢弃了管道,因此您不必担心那里的效率低下。更重要的是用户空间进程应该有一致的体验,这意味着除非特别要求,否则不要关闭描述符。

【讨论】:

    【解决方案2】:

    文件描述符不会被系统关闭,直到进程退出。对于管道以及任何其他文件描述符都是如此。

    没有数据的管道(或任何其他文件)与封闭的文件描述符之间存在很大差异。
    当文件描述符关闭时,系统可以将其编号重新用于新的文件描述符。然后,当您阅读时,您会得到其他东西。所以在你关闭了一个文件描述符之后,你就不能再使用它了。

    现在想象一下,一旦没有更多数据,系统会自动关闭文件描述符。这将使该号码可供重用,随后的不相关打开可能会得到它。现在不知道没有更多数据的读取器将从它认为是管道的内容中读取,但实际上会从另一个文件中读取。

    【讨论】:

      猜你喜欢
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多