2009-08-21 41 views
2

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

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

谢谢!

+0

Windows中的CreateProcess具有'bInheritHandles'标志来处理这个问题 - 寻找UNIX/Mac OS等价物。 – psychotik 2009-08-21 00:30:22

回答

0

经过一番试验后,我发现Mac上的'open'shell命令创建了一个不会继承父文件/端口的进程。将“open foo.app”作为参数调用到系统函数中会有诀窍。当然,这只是mac。对于Unix,这里提出的其他方法之一很有意义。

+0

open命令告诉launchd生成进程(或在现有进程中打开文档),因此您不是其父进程。这就是为什么它不会继承你的任何东西。 – mark4o 2009-08-22 08:20:34

+0

@ mark4o运行'open'会导致生成的进程继承环境变量(如果从终端而不是Finder打开应用程序,则会得到不同的环境)。 – jpc 2012-09-21 23:01:11

10

您没有指定您正在开发的语言,但自从您提到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; 
} 

希望帮助,

埃里克Melski

1

在Mac OS X中,可以使用读取目录/dev/fd/opendir()/readdir()来确定一套开放的文件描述符。有了这些信息,您可以调用fcntl(FD, F_SETFD, FD_CLOEXEC)每个打开的文件描述符,或者你可以分叉后调用每个文件描述符close(FD)

请参阅Getting the highest allocated file descriptor了解一些其他详细信息,包括其他系统的方法。

0

@Eric M:你的回答让我了解了大部分的途径,但是我发现它仍然留下了一些文件描述符。我用getdtablesize()替换了上面代码中的sysconf(OPEN_MAX),它效果很好。谢谢您的帮助!