2012-07-19 74 views
3

分叉管道子流程的最佳技術是什麼?分叉管道子流程

我的當前程序需要運行另一個進程,這些進程實際上是通過管道連接的幾個命令。我不需要知道命令的輸出,只要它們失敗或成功,所以我正在使用fork/exec。

在命令行上的等效將是

/path/to/A arg1 arg2 | /path/to/B argB1 | /path/to/C 

注意:使用的腳本是不實際的,因爲它的A/B/C在未來可能改變。

這兩種技術我雖然是:

  1. 遞歸叉。在下一個分支中連接可用於子項的父項(輸入到其父項)輸出。

  2. 在頂層創建所有管道。
    然後使用一個循環來分支所有可以適當地連接管道的孩子。

+2

後者是什麼貝殼做,大概是一個很好的理由。 – 2012-07-19 20:21:14

+0

@OliCharlesworth:你有參考嗎?或者最好鏈接到示例代碼,所以我不重新發明輪子。 – 2012-07-19 20:22:28

+0

如果你在使用Linux,你可以通過運行'pstree'來推斷它,它顯示所有進程的父子關係。 – 2012-07-19 20:33:44

回答

1

不要遞歸遞歸。使B成爲A的子進程並不是一個好主意。例如,如果B調用setsid在自己的會話中運行,它將採用與它無關的A.如果B死了,A會得到一個SIGCHILD,而不是你。尤其是,您將無法獲得B的返回狀態。

下面是在一系列管道上分叉n個子代碼的草圖。警告:我直接在瀏覽器中輸入代碼;可能有很多錯別字,我省略了所有錯誤檢查。

char *executables[n]; 
char *args[n]; 
int pipes[2*n+2]; /* child i reads from */ 
int child_pids[n]; 
int ret; /*Error checking omitted; abort if ret ever becomes negative*/ 
ret = pipe(pipes); 
for (i = 0; i < n; i++) { 
    ret = pipe(pipes + 2 * i + 2); 
    ret = fork(); 
    if (ret == 0) { 
     /* Code of child i */ 
     close(pipes[2*i+1]); 
     close(pipes[2*i+2]); 
     dup2(pipes[2*i], 0); 
     dup2(pipes[2*i+3], 1); 
     ret = execv(executables[i], args[i]); 
    } 
    close(pipes[2*i]); 
    close(pipes[2*i+3]); 
    child_pids[i] = ret; 
} 
/* interact with the subprocesses, then call wait or waitpid as needed */ 
0

如果你在一個unix,一個簡單的system("/path/to/A arg1 arg2 | /path/to/B argB1 | /path/to/C")會做你想做的。它調用一個shell作爲/bin/sh -c $STRING_PASSED_TO_SYSTEM。如果您想要更好的控制,例如讀取輸出或寫入輸入的能力,請考慮C庫中的popen()例程。

+1

不要真的想使用system()或popen()。我正在使用的一些論點在複雜的一面有點偏差,並且獲得引用和轉義引用會得到很好的結果。我想使用execvp()來確保參數正確傳遞給子進程。 – 2012-07-19 20:26:48

+0

我向你保證,正確的命令轉義比創建工作管道鏈更簡單。或者,也可以將帶有怪異參數的命令包裝在腳本或變體版本中,這些腳本或變體版本通過文件等獲取它們的參數。獲取所有pipe()/ dup()/ fork()/ exec()邏輯的過程是正確的多毛和容易出錯。正如Oli在上面指出的那樣,shell已經爲你做了。 – 2012-07-19 20:32:11