在OSX / Unix上启动不继承文件/端口的子进程

时间:2009-08-21 00:25:05

标签: macos unix process

我想在OS X上启动子进程,以便子进程不继承当前进程的打开文件/端口。

有关如何完成此任务的任何建议?我可以使用system()函数调用的Shell命令也可以工作 - 我只是不知道有一个好的shell命令可以启用它。

谢谢!

4 个答案:

答案 0 :(得分:11)

您没有指定您正在开发的语言,但自从您提到system()后,我认为您的意思是C或C ++。

通常这是通过使用fcntl()在那些你不想继承的文件描述符上设置close-on-exec标志来实现的:

int fd = open("somefile", O_RDONLY);
fcntl(fd, F_SETFD, FD_CLOEXEC);

你也可以通过在fork之后但在exec之前遍历子进程中的所有可能的fd来执行暴力破解方式。这有点棘手,因为它要求你知道最大可能的fd值是多少,而且效率也会降低,因为你最终会迭代并“关闭”一堆未使用的fd。像这样:

pid_t pid = fork();
switch (pid) {
    case 0:
        // In the child process.  Iterate through all possible file descriptors
        // and explicitly close them.

        long maxfd = sysconf(OPEN_MAX);
        for (long i = 0; i < maxfd; ++i) {
            close(i);
        }

        // Now exec the new program, file-handle free.

        execlp("someprogram", "arg1", "arg2");
        break;
    case -1:
        // TODO: handle errors.

        break;
    default:
        // Parent process.

        int status;
        pid_t finished = waitpid(pid, &status, 0);
        break;
}

希望有所帮助,

Eric Melski

答案 1 :(得分:1)

在Mac OS X上,您可以使用/dev/fd/ / opendir()读取目录readdir()来确定打开的文件描述符集。有了这些信息,您可以在每个打开的文件描述符上调用fcntl( fd , F_SETFD, FD_CLOEXEC),也可以调用close( fd {分叉后的每个文件描述符上的{1}}。

有关其他详细信息,请参阅Getting the highest allocated file descriptor

答案 2 :(得分:0)

经过一些实验,我发现Mac上的'open'hell命令创建了一个不继承父文件/端口的进程。调用'open foo.app'作为系统函数的参数就可以了。当然,这只是mac。对于Unix,这里建议的其他方法之一很有意义。

答案 3 :(得分:0)

@Eric M:你的回答让我大部分都在那里,但我发现它仍然留有一些文件描述符。我将上面代码中的sysconf(OPEN_MAX)替换为getdtablesize(),效果很好。谢谢你的帮助!