2011-03-07 46 views
8

我有多個孩子受同一母公司「分叉」,我試圖建立像一個鏈表結構,所有這些子進程之間pipe連接創建兩個子進程之間有管道。孩子1將數據發送給孩子2,孩子2發送給孩子3 ....孩子N發送給孩子1.是否有任何適當的方式來做到這一點?另外,如果我在兩個進程之間創建和通信,我強制父進程等待所有進程完成他們的工作,因爲wait()waitpid()等待第一個完成的進程,但我需要等待所有進程。這是另一個問題出現。是否有可能由相同的父(LINUX,POSIX)

謝謝...

回答

17

這實質上是一個殼做什麼,如果建立一個重定向鏈,即像

ls | grep foo | sort | uniq 

有在Unix編程的一些優秀introducionary文本,其中一個簡單的外殼是通過這本書來實現。而一個shell的任務之一就是重定向。其中一本書是Michael K. Johnson和Erik W. Troan的「Linux Application Programming」。

本書的主頁:http://ladweb.net/

要構建重定向鏈N個處理需要N-1的管道。對於每個重定向,您使用系統調用pipe(int fds[2])來創建管道。後fork() ING,但在此之前execv荷蘭國際集團使用dup2(int from, int to)到管的端「連接」到標準輸入(0)或每個過程的標準輸出。這裏是一個過分簡化代碼,沒有錯誤檢查:

int pipe_A[2]; 
int pipe_B[2]; 

pipe(pipe_A); 
pipe(pipe_B); 

pid_t pid_A, pid_B, pid_C; 

if(!(pid_A = fork())) { 
    dup2(pipe_A[1], 1); /* redirect standard output to pipe_A write end */ 
    execv(...); 
} 

if(!(pid_B = fork())) { 
    dup2(pipe_A[0], 0); /* redirect standard input to pipe_A read end */ 
    dup2(pipe_B[1], 1); /* redirect standard output to pipe_B write end */ 
    execv(...); 
} 

if(!(pid_C = fork())) { 
    dup2(pipe_B[0], 0); /* redirect standard input to pipe_B read end */ 
    execv(...); 
} 

,請注意該管的數組索引已經在某種程度上被choosen它們反映標準輸入/輸出的文件描述符,如果他們使用標準輸入輸出重定向。這個選擇並不是任意的。當然,你可以將管道連接到任何文件描述符(例如有一些應用程序,它們的父級打開,比如fd 3和4,連接到管道),大多數shell也直接支持這個(例如1 > & 3將把stdout重定向到fd 3)。然而pipe(int fds[2])的數組索引當然是0和1。我只是告訴這一點,因爲我有一些貨物邪教編程的學生,其盲目地把目標FDS還爲管系統調用數組。

等待所有的孩子完成使用waitpid(-1, NULL, 0) - 我認爲這是-1我的預答覆者的意思,這意味着:等待所有的子進程完成。另一種選擇是在循環中調用wait(),該循環將返回剛剛結束的子節點的PID。如果再次調用並且仍有小孩在跑步,則會再次阻止。如果沒有孩子,它將返回-1;我更喜歡waitpid解決方案。

+0

快速的問題,當我使用上面的代碼我的程序掛在第二個execv,我認爲它正在等待stdin的EOF。 我打算如何關閉stdin? – TrewTzu 2011-09-04 05:22:34

+0

@TrewTzu:您必須在用dup2(pipe_A [0],0)替換它之後才關閉stdin,因爲它會關閉管道。我也不明白爲什麼execv應該阻止。但是execv不會返回,它會用被調用的程序替換進程。這就是爲什麼這個過程是事先分出來的。你在試用這個操作系統?只是好奇。 – datenwolf 2011-09-04 09:13:03

+0

這有點晚,但看着這段代碼,不應該將隨後的if語句改爲「else if」嗎?否則,第一個分支的孩子和父母都會運行第二個分支。 – 2013-04-23 18:05:17

2

首先創建所有的管道,然後產卵所有的孩子用適當的管道中的FD 0結束,1

至於等待,只需等待返回-1 。

+0

我沒有得到「只是一直等到它返回-1」。你什麼意思?你的意思是「等待(-1);」或者是什麼? – erogol 2011-03-07 22:20:58

+0

繼續在循環中調用它,直到它返回-1。 – 2011-03-07 22:25:25

3

是的,這很容易,你只需要在父級創建所有管道,並且記得關閉你不需要它們的子(管道)中的管道/管道末端。

離開管在不使用它們是一個失敗的孩子開放的文件描述符,因爲它可以讓別人永遠等待管道的末端。讀者獲得EOF之前,所有作者都必須關閉。

相關問題