popen() 实现、fd 泄漏和 vfork()

popen() implementation,fd leaks,and vfork()

popen()的glibc实现中,指定了

The popen() function shall ensure that any streams from previous popen() calls that remain open in the parent process are closed in the new child process.

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

popen() 的 glibc 实现使用 fork()。虽然在fork()exec()之间有dup2()close()调用,但是否可以用vfork()替换fork()以提高性能?

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

我要写一个双向版本的 popen(),其中 returns 两个 FILE*:一个用于读取,一个用于写入。我该如何正确实施?它应该是线程安全的并且没有 fd 泄漏。快点更好

vfork(2) is obsolete (removed from POSIX2008), and fork(2) is quite efficient, since it uses copy-on-write 技巧。

popen(3) cannot close all opened files, because it does not know them and cannot know which are relevant. Imagine a program which gets a socket and pass its file descriptor as an argument to the popen-ed command (or simply popen("time cat /etc/issue >&9; date","r")....). See also fcntl(2) with FD_CLOEXEC, open(2) with O_CLOEXEC, execve(2)

文件描述符是程序范围和进程范围的稀缺资源,您有责任正确管理它们。在execve之前,你应该知道在你的子进程中应该关闭哪些fd-s。如果你知道什么程序是 execve-d 以及它需要什么 fds,你可以在 execve 之前 close 所有其他 fds(或者其中的大部分,可能带有 for (int i=STDERR_FILENO+1; i<64; i++) (void) close(i);)。

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

看起来您正在重新发明 p2open (then you probably need to understand the implementation details of your FILE in your C standard library, or else use fdopen(3) with care and caution); you might find some implementation of it. Beware, the process using that probably need to have some event loop (e.g. above poll(2) ...) 以避免潜在的死锁(父进程和子进程在读取时都被阻塞)。

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

顺便说一句 Linux 有几个 free software implementations for its C standard library. The GNU libc is quite common, but there is musl-libc 和其他几个。研究你的 libc 的源代码。