我正在实现一个库来运行命令。该库是C,在Linux上。
它当前执行popen()调用来运行命令并获取输出。问题是该命令继承了所有当前打开的文件处理程序。
如果我做了一个fork / exec,我可以明确地关闭孩子的处理程序。但这意味着重新实现popen()。
我可以在所有处理程序上设置close-on-exec而不必逐个循环它们吗?
我可以将close-on-exec设置为进程的默认值吗?
谢谢!
答案 0 :(得分:27)
不,不。
您只需要小心并在您关注的所有文件描述符上设置close-on-exec。
但设置很简单:
#include <fcntl.h>
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#include <unistd.h>
/* please don't do this */
for (i = getdtablesize(); i --> 3;) {
if ((flags = fcntl(i, F_GETFD)) != -1)
fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
}
如果您运行的Linux内核≥2.6.23且glibc≥2.7,则open
(以及其他类似的系统调用)会接受新标记O_CLOEXEC
:
#include <unistd.h>
fd = open("...", ... | O_CLOEXEC);
如果您运行的Linux内核≥2.6.24且glibc≥2.7,则fcntl
接受新参数F_DUPFD_CLOEXEC
:
#include <fcntl.h>
newfd = fcntl(oldfd, F_DUPFD_CLOEXEC);
如果您运行的Linux内核≥2.6.27且glibc≥2.9,则会有新的系统调用pipe2
,dup3
等,还有更多的系统调用会获得新的*_CLOEXEC
标志:
#define _GNU_SOURCE
#include <unistd.h>
pipe2(pipefds, O_CLOEXEC);
dup3(oldfd, newfd, O_CLOEXEC);
popen()函数应确保在新的子进程中关闭在父进程中保持打开的先前 popen()调用的任何流。
所以,如果您担心 泄漏,请不要。
答案 1 :(得分:-2)
有点老问题,但如果在getpid()
之后使用fork()
,请查看/proc/PID/fd/
目录并关闭您在那里找到的所有描述符(0,1,2和0除外)你从opendir()
)然后execve()
获得的那个?