2

在 的 glibc 实现中popen(),它指定

popen() 函数应确保在父进程中保持打开的先前 popen() 调用的任何流在新的子进程中关闭。

为什么?如果目的是避免 fd 泄漏,为什么不关闭所有打开的 fd?

popen()使用的 glibc 实现fork()。虽然 and 之间有dup2()andclose()调用fork()exec()是否可以替换fork()byvfork()来提高性能?

Linux 的实现是popen()基于fork()而不是vfork()?为什么或者为什么不)?

我将编写 的双向版本popen(),它返回两个FILE*:一个用于读取,一个用于写入。如何正确实施?它应该是线程安全的并且没有 fd 泄漏。如果速度快就更好了。

4

1 回答 1

2

vfork(2)已过时(从 POSIX2008 中删除),并且fork(2)非常有效,因为它使用了写时复制技术。

popen(3)不能关闭所有打开的文件,因为它不知道它们,也不知道哪些是相关的。想象一个程序,它获取 asocket并将其文件描述符作为参数传递给popen-ed 命令(或简单地说popen("time cat /etc/issue >&9; date","r")......)。另请参见fcntl(2)FD_CLOEXECopen(2)O_CLOEXECexecve(2)

文件描述符是程序范围和进程范围的稀缺资源,正确管理它们是您的责任。您应该知道在您的子进程之前应该关闭哪些 fd-s execveexecve如果您知道-d是什么程序以及它需要什么closefds ,那么您可以for (int i=STDERR_FILENO+1; i<64; i++) (void) close(i);execve.

如果您正在编写可重用库,请记录其有关文件描述符(以及任何其他全局进程范围资源)的策略,并可能用于FD_CLOEXEC它自己获取的任何文件描述符(不是作为显式参数或数据),例如供内部使用。

看起来您正在重新发明p2open(那么您可能需要了解您FILE在 C 标准库中的实现细节,或者小心谨慎地使用fdopen(3));你可能会找到它的一些实现。请注意,使用它的进程可能需要一些事件循环(例如,在poll(2) ... 之上)以避免潜在的死锁(父进程和子进程在读取时都被阻塞)。

您是否考虑过使用一些现有的事件循环基础设施(例如libeventlibev、 GTK 的glib等......)?

顺便说一句,Linux为其C 标准库提供了几个免费软件实现。GNU libc很常见,但还有musl -libc和其他几个。研究你的 libc 的源代码。

于 2015-09-10T12:05:43.300 回答