2014-09-30 24 views
0

林相當新的C,我不確定如何繼續。從父母讀取和寫入多個孩子與執行程序

有了這段代碼,我試圖創建多個子進程,將他們的標準輸出發送到他們的父母stdin,並讓他們的標準輸入寫入數組中的指針位置的fdprintf。

代碼似乎當一個基本的程序,讀取標準輸入並打印到標準輸出(應管道回)執行到不行。 (在主代碼的不同部分,我將fprintf指向管道啓動的地方,然後讀取stdin等待應該寫回的內容)。

int plumber(int *pipes[], int numChildren, char* command[]) { 
    int i; 
    char id; 
    int nullSpace = open("/dev/null", O_WRONLY); 

    for(i = 0; i < numChildren; ++i) { 
     id = 'A' + i; 
     pipe(pipes[2 * i]); 
     pipe(pipes[2 * i + 1]); 
     switch(fork()) { 
      case (-1): 
       fprintf(stderr, "Unable to start subprocess\n"); 
       exit(4); 
       break; 
      case 0: 
       //child 
       //close child's write, dupe its stdin to read 
       //close childs old read 
       close(pipes[2 * i][1]); 
       if(dup2(pipes[2 * i][0], 0) == -1) { 
        fprintf(stderr, "Unable to start subprocess\n"); 
        exit(4); 
       } 
       close(pipes[2 * i][0]); 
       //close child's read, dupe its stdout to write 
       //close childs old write 
       close(pipes[2 * i + 1][0]); 
       if(dup2(pipes[2 * i + 1][1], 1) == -1) { 
        fprintf(stderr, "Unable to start subprocess\n"); 
        exit(4); 
       } 
       close(pipes[2 * i + 1][1]); 
       close(1); 
       //child stderr to nullspace 
       if(dup2(nullSpace, 2) == -1) { 
        fprintf(stderr, "Unable to start subprocess\n"); 
        exit(4); 
       } 
       close(2); 
       execlp(command[i], "childprocess", numChildren, id, NULL); 
       break; 
      default: 
       //parent 
       //close read pipe from writing pipe 
       close(pipes[2 * i][0]); 
       //close write pipes and dupe stdin to read 
       //close parents old read 
       close(pipes[2 * i + 1][1]); 
       if(dup2(pipes[2 * i + 1][0], 0) == -1) { 
        fprintf(stderr, "Unable to start subprocess\n"); 
        exit(4); 
       } 
       close(pipes[2 * i + 1][0]); 
     } 
    } 
    close(nullSpace); 
    return 0; 
} 

的指令才運行的子進程這也需要孩子的數目和從A至D的ID *管[]是numChildren的* 2乘2(沿着它的子1讀管那麼回事,child1寫管道,讀的child2,寫的child2等 請在此先感謝幫助和

回答

0

父只能有一個stdin每次父母做:。

dup2(pipes[2 * i + 1][0], 0) 

它正在關閉其前面的stdin並替換它與管道的讀取結束。這意味着,所有的孩子,除了最後,將有一個封閉的讀取結束,這應該引起他們接受一個SIGPIPE(或EPIPE錯誤如果SIGPIPE被忽略),如果他們試圖產生任何輸出stdout。此外,家長現在已經失去了原來的stdin,這可能或可能不重要。

您也應該檢查execlp沒有返回一個錯誤。如果是這樣,你會得到非常奇怪的行爲,因爲失敗的孩子將開始與父母同時產生所有剩餘的孩子。

如果你真的希望所有的孩子們的輸出出現在一個單一的stdin,那麼他們必須全部使用同一管道。然而,這將導致他們的輸出變得隨機混合,所以父母不可能知道誰發送了什麼。它會更好,如果家長只是不停每個管道的讀端在其原有的描述,而不是試圖dup2他們0。這樣一來,母公司將保留其原有的stdin,並且它可以使用select(或poll,或...)來確定何時獲得輸入以及來自哪個孩子。

將孩子的stdinstdout連接到相同的進程(父進程)通常是一個壞主意,因爲它很容易導致死鎖。管道只能緩衝有限數量的數據,並且會在寫滿時反壓(即阻塞)寫入器。如果父母雙方都將大量的數據寫入他們的stdouts,他們都會受到壓力,這將阻止他們讀取輸入和排空管道。您必須確保孩子在生成自己的任何輸出前消耗父母的所有輸出,或者找到一種方法來保證即使stdout被阻止,您也可以始終從stdin中讀取。後者可通過具有單獨的線程處理stdinstdout,或者通過啓用非阻塞I/O,並使用select等,以確定何時管可寫入來完成。