为啥 Linux 会重用 pipe() 分配的文件描述符

Posted

技术标签:

【中文标题】为啥 Linux 会重用 pipe() 分配的文件描述符【英文标题】:Why would Linux reuse a file descriptor allocated by pipe()为什么 Linux 会重用 pipe() 分配的文件描述符 【发布时间】:2011-01-22 03:01:24 【问题描述】:

我发现在 Linux 中同时使用套接字和管道存在问题。具体来说,我们调用 pipe(),它分配接下来的两个可用文件描述符……比如说 10 和 11。然后我们在套接字上调用 accept(),期望它分配 12。相反,它分配了 11。

我们进行了一些测试,似乎从 pipe() 返回的第二个 FD 始终可供其他创建文件描述符的系统调用重用。

谁能解释一下?

【问题讨论】:

明确一点 - 您已经检查了管道调用的返回码,一切都很好吗?你没有用 fork() 或任何东西做任何时髦的事情吗?只是一个直接的 pipe() 调用,然后是一个 accept()? @Duck 只是为了指出一些事情,他确实在套接字上说了 accept() ......因此我编辑了我的答案...... 【参考方案1】:

这意味着有人在调用管道之后和第二个系统调用之前的某个时间关闭了有问题的文件描述符。例如,如果您分叉一些其他进程以在管道的一端执行操作,那么您可能会搞砸关闭​​另一个进程使用的管道末端并关闭错误的管道末端的代码。或者几乎任何其他可能在某些文件描述符上调用 close 的东西都可能正在关闭错误的东西。

【讨论】:

【参考方案2】:

也许标志 SO_REUSEADDR 用于管道,因此您没有看到文件描述符编号增加?

编辑:感谢 duckdarron 的提醒我愚蠢的回答。我正在阅读这个link,如果在文件描述符上调用close(),它会被重用......

希望这会有所帮助, 最好的祝福, 汤姆。

【讨论】:

我假设他在谈论未命名/匿名管道。甚至不会有 SO_REUSEADDR 可以重用的地址。 SO_REUSEADDR 与文件描述符编号无关。它指的是套接字地址(IP 和端口)。 @Duck:管道和插座很相似……这就是我建议的原因? 可以理解。我的猜测是他正在关闭一个管道描述符并在接受时重用。时间会证明一切。

以上是关于为啥 Linux 会重用 pipe() 分配的文件描述符的主要内容,如果未能解决你的问题,请参考以下文章

linux下fork两子进程为啥只有一个读取到pipe的内容?

为啥 PIPE 文件的 readline() 这么慢?

为啥 fs.createReadStream ... pipe(res) 锁定读取文件?

Linux pipe 源代码分析

鸟哥的Linux,为啥要分配BIOS boot分区?为啥/boot要分配1G这么多?

为啥 UIStackView 中的 UILabel 在重用时会失去高度?