2009-08-21 38 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),它效果很好。謝謝您的幫助!