我们是否需要显式关闭管道的读取端,其写入结束已被关闭?

时间:2012-08-06 10:24:52

标签: c pipe fgets inter-process-communicat

我有以下情况。

  1. 我创建了一个管道。

  2. 分叉一个子进程。

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

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

  5. 现在我的问题是,为什么父母需要在读完后明确地关闭管道的读取端?一旦从读端读取完整的数据,系统是否完全删除管道是不明智的?

    我在父节目中明确地关闭了读取端,并且在打开更多管道时迟早会出现Too many file descriptors错误。我的假设是,一旦管道写入结束并且数据已从读取端完全读取,系统会自动删除管道。你有两次从管道出来了吗?

    那么,一旦数据被完全读取并写入结束,系统背后的理由是不删除管道?

2 个答案:

答案 0 :(得分:7)

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

系统仍然可以判断管道一端的所有描述符何时被关闭(显式或因为退出拥有过程)。关闭管道另一端的那些仍然没有意义,因为当父进程试图关闭管道末端的描述符时会导致混淆;之一:

  • 系统关闭了fd,在这种情况下尝试关闭已经关闭的fd时出现错误;或
  • fd已被重复使用,这更糟糕,因为它现在正在关闭一个完全不相关的fd。

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

答案 1 :(得分:5)

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

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

现在想象一下,一旦没有更多数据,系统就会自动关闭文件描述符。这将使该数量可供重用,并且随后的无关打开可以获得它。现在,那个还不知道没有更多数据的读者会从它认为是管道的内容中读取,但实际上会读取另一个文件。