2011-12-19 58 views
4

任何人都可以告訴我這段代碼有什麼問題嗎?叉執行管重定向問題

總之,它創建輸入和輸出管道和fork-exec的sort程序。父母讀取字典/usr/share/dict/words,並將其寫入dup2()'d到sort的管道中,並同樣從中讀取輸出,並將其打印到終端(父母的標準輸出)。或者至少,這就是應該發生的事情。

回溯表示父母掛在130行的read()(標記爲'XXX'註釋)。這幾乎就好像sort不知道文件結束,但關閉pipeIn的寫入結束應該'發出'這個信號,對嗎?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h> 

int main(int argc, char** argv) 
{ 
    int pipeIn[2]; 
    int pipeOut[2]; 

    if ((pipe(pipeIn)) == -1) 
    { 
     perror("pipe"); 
     exit(EXIT_FAILURE); 
    } 

    if ((pipe(pipeOut)) == -1) 
    { 
     perror("pipe"); 
     exit(EXIT_FAILURE); 
    } 

    pid_t child = fork(); 

    if (child == 0) 
    { 
     // This is child! 

     if ((dup2(pipeIn[0], STDIN_FILENO)) == -1) 
     { 
      perror("dup2"); 
      exit(EXIT_FAILURE); 
     } 

     if ((dup2(pipeOut[1], STDOUT_FILENO)) == -1) 
     { 
      perror("dup2"); 
      exit(EXIT_FAILURE); 
     } 

     if ((dup2(pipeOut[1], STDERR_FILENO)) == -1) 
     { 
      perror("dup2"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeIn[0])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeOut[1])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     if ((execlp("sort", "-r", NULL)) == -1) 
     { 
      perror("execlp"); 
      exit(EXIT_FAILURE); 
     } 
    } 
    else if (child == -1) 
    { 
     perror("fork"); 
     exit(EXIT_FAILURE); 
    } 
    else 
    { 
     // This is parent! 

     if ((close(pipeIn[0])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeOut[1])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     int dict = open("/usr/share/dict/words", O_RDONLY); 

     if (dict == -1) 
     { 
      perror("open"); 
      exit(EXIT_FAILURE); 
     } 

     char buf[1024]; 
     int count; 

     while ((count = read(dict, buf, sizeof(char) * 1024)) > 0) 
     { 
      putchar('.'); 

      if ((write(pipeIn[1], buf, count)) == -1) 
      { 
       perror("write 1"); 
       exit(EXIT_FAILURE); 
      } 
     } 

     if (count == -1) 
     { 
      perror("read"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(dict)) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeIn[1])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 

     while ((count = read(pipeOut[0], buf, sizeof(char) * 1024)) > 0) // XXX 
     { 
      putchar('!'); 

      if ((write(STDOUT_FILENO, buf, count)) == -1) 
      { 
       perror("write 2"); 
       exit(EXIT_FAILURE); 
      } 
     } 

     if (count == -1) 
     { 
      perror("read"); 
      exit(EXIT_FAILURE); 
     } 

     if ((close(pipeOut[0])) == -1) 
     { 
      perror("close"); 
      exit(EXIT_FAILURE); 
     } 
    } 

    return EXIT_SUCCESS; 
} 

謝謝你的任何意見(赦免雙關語)。

+0

可能重複之前的某處添加以下代碼://計算器。問題/ 916900 /有trouble-with-fork-pipe-dup2和exec-in-c) – wallyk 2011-12-19 00:14:31

+0

我已經閱讀過,看起來相當不同。 – Doddy 2011-12-19 00:16:48

+0

我同意 - 交叉引用的問題有所不同。 – 2011-12-19 03:37:27

回答

2

您的問題是,您沒有關閉智利進程中管道未使用的末端。所以,你需要[用C具有與叉(),管(),DUP2()的麻煩和exec()](HTTP的exec

if ((close(pipeIn[1])) == -1) 
    { 
     perror("close"); 
     exit(EXIT_FAILURE); 
    } 

    if ((close(pipeOut[0])) == -1) 
    { 
     perror("close"); 
     exit(EXIT_FAILURE); 
    } 
+0

+1 - 你說得對。這是違反直覺的,但是如果你在一個子進程中使用一個管道作爲標準輸入或者標準輸出,那麼你通常最終會關閉由'pipe()'返回的兩個文件描述符**。 – 2011-12-19 03:36:01

+0

是的,我一開始並沒有得到它,但現在我想到了它(我直到今天從來沒有這樣想過)。在fork之後,實際上有兩個可以寫入管道的開放文件描述符。因此,在讀取管道時,無法讀取'eof',直到寫入結束的所有文件描述符都被關閉。 – Sodved 2011-12-19 05:49:22

+0

謝謝,它正在工作,但它不是按相反順序打印單詞列表。 'execlp(「sort」,「-r」,NULL)的語法是錯誤的嗎? – Doddy 2011-12-19 14:22:44