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

Pav*_*ath 10 c pipe fgets inter-process-communicat

我有以下情况.

  1. 我创建了一个管道.

  2. 分叉儿童过程.

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

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

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

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

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

eca*_*mur 7

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

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

  • fd已被系统关闭,在这种情况下,当它试图关闭已经关闭的fd时会出现错误; 要么
  • fd已被重用,这更糟糕,因为它现在正在关闭一个完全不相关的fd.

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


ugo*_*ren 5

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

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

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