2013-01-11 163 views
0

我正在嘗試重寫執行類似ls | wc | wc的ac程序,我已經爲ls執行了它| wc,它工作正常,但我無法弄清楚爲什麼我的程序停在指定行的孩子身上。請幫忙!在C中使用fork管道兩次使用linux linux

int main (void) 
{ 
    pid_t pid_fils, pid_pfils; 

    int fd[2], fd2[2]; 

    if(pipe(fd)==-1 || pipe(fd2)==-1) 
    { 
     printf("pipe failed!"); 
     return 1; 
    } 

    printf("program started\n"); 
    pid_fils=fork(); 
    if(pid_fils==0) 
    { 
     pid_pfils=fork(); 
     if(pid_pfils==0) 
     { 
      //action3 
      printf("I am the grandson\n"); 
      close(fd[0]);//close read side 
      dup2(fd[1],1);//connect write with stdout 
      close(fd[1]);//close write side 
      execlp("ls","ls",(char*)0); 
      //execvp("ls",argv3); 
      return 0;/*actions grandson*/ 
     } 
     else 
     { 
      //action2 
      printf("I am the son\n"); 
      wait(); 
      printf("son, wait ok\n"); 
      >close(fd[1]); //close read side 
      >dup2(fd[0],0); //connect write with stdin 
      >close(fd[0]); //close read side 

      ///////pipe2//// 
      > close(fd2[0]); //close read side 
      >dup2(fd2[1],1); //connect write with stdout/*it stops here -can't display "ok!"*/ 
      printf("ok!\n");  
      >close(fd2[1]); //close write side 

      execlp("wc","wc",(char*)0); 
      printf("error exec returned!\n");  
      return 0; 
     } 
    } 
    else 
    { 
     ///action1 
     printf("I am the parent\n"); 
     wait(); 
     printf("parent,wait ok\n"); 
     close(fd2[1]); //close write side, 
     dup2(fd2[0],0); //connect read with stdin 
     close(fd2[0]); //close read side 
     execlp("wc","wc",(char*)0); 
     return 0;/*the parent*/ 
    } 
    return 1; 
} 
+0

請修剪您的代碼以僅包含相關部分。 –

+3

使用'fprintf(stderr,...''將所有內容打印到stderr中,這將有助於確保診斷不會進入管道,並且*總是*向stderr寫入錯誤消息,例如'perror(「pipe failed」 )'比'printf(「pipe failed」)'更有用 –

回答

3

確保關閉所有未使用的描述符。在你的情況下,最簡單的解決方案是將管道(fd)的創建移動到第一個if塊(在第一個子過程中)。問題是,只要任何進程可能寫入管道,讀取器就不會得到EOF,因此不會終止。

if(pipe(fd2)==-1) 
{ 
    printf("pipe failed!"); 
    return 1; 
} 

printf("program started\n"); 
pid_fils=fork(); 
if(pid_fils==0) 
{ 
    if(pipe(fd)==-1) 
    { 
     printf("pipe failed!"); 
     return 1; 
    } 
    pid_pfils=fork(); 

我還應該提一下,你可能想重新考慮等待電話。不知道你打算如何處理它們,但你不希望「ls」進程阻止輸出,因爲讀者還沒有開始。

1
dup2(fd2[1],1); 

以上線將第一關閉該文件在描述符1,然後重複從FD2的decriptor [1]到1.

1是標準輸出。這意味着調用關閉標準輸出。

的printf打印到stdout,這意味着printf的打印到1這是目前分配給管FD2

所以你確定進入管道,而不是在屏幕上。

嘗試

 //action2 
     printf("I am the son\n"); 
     wait(); 
     printf("son, wait ok\n"); 
     close(fd[1]); //close read side 
     dup2(fd[0],0); //connect write with stdin 
     close(fd[0]); //close read side 

     ///////pipe2//// 
     int my_terminal_out = dup(1); 
     close(fd2[0]); //close read side 
     dup2(fd2[1],1); //connect write with stdout/*it stops here -can't display "ok!"*/ 
     fprintf(my_terminal_out, "ok!\n");  
     close(fd2[1]); //close write side 

未經測試。你也應該測試你的其他代碼的類似失誤。

+ DrC說的。