2016-11-07 49 views
1

我還不熟悉進程,管道和dup2,因此我希望有人能幫我弄清楚我創建的程序有什麼問題。這個程序應該運行ls | wc。到目前爲止輸出我得到的是:使用進程通過管道運行命令

wc : standard input : Bad file descriptor 
     0   0   0 
ls : write error : Bad file descriptor 

後,我得到這個輸出,終端仍然接受輸入。這就像wc仍然在運行,儘管如果我先放置類似ls的命令(之前沒有任何其他輸入),它將運行它們並關閉。我試着在/之前/之後運行ps,並且程序仍在運行,並且沒有顯示任何打開bash和ps的進程。 (我運行此程序在Linux終端)

這裏是我的代碼:

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

int main(int argc, char* argv[]){ 
     pid_t pid; 
     int fd[2]; 
     char com1[1024] = ("ls"); 
     char com2[1024] = ("wc"); 
     pipe(fd); 
     pid = fork(); 
     if(pid == 0){ 
      open(fd[1]); 
      dup2(fd[0],STDOUT_FILENO); 
      close(fd[0]); 
      execlp(com1, com1, NULL); 
        } 
     else { 
      pid = fork(); 
      if (pid == 0){ 
        open(fd[0]); 
        dup2(fd[1],STDIN_FILENO); 
        close(fd[1]); 
        execlp(com2, com2, NULL); 
         } 
      } 
return 0; 
} 

記住,我一定知道,如果需要檢查命令(如if(pid<0)exit(0);),但我想簡化我的代碼儘可能多地查看是否由於粗心導致任何錯誤。 提前謝謝!

+0

這是否代碼甚至編譯?它至少應該使編譯器對你發出警告。調用'open(fd [0])'(當然'open(fd [1])')是無效的,應該刪除。 –

+0

至於你的問題,我建議你閱讀[管'手冊頁](http://man7.org/linux/man-pages/man2/pipe.2.html)。請密切注意哪些描述符是管道的讀取和寫入結束。 –

+0

此代碼編譯沒有任何錯誤到目前爲止,我刪除了open()命令,並得到相同的輸出 –

回答

0

根據the pipe manual page

pipefd[0]指管的讀端。 pipefd[1]指的是管道的寫入結束。

現在從第一個孩子這一行,調用ls命令的過程:

dup2(fd[0],STDOUT_FILENO); 

在這裏,您複製閱讀管結束STDOUT_FILENO,即,其中輸出寫入。如果你停下來思考一下,你會如何寫入一個只讀的文件描述符如fd[0]

與其他子進程相同,你在這裏編寫寫入管道標準輸入結束。

解決方法很簡單:交換重複描述符的位置。第一個子進程使用fd[1],第二個子進程使用fd[0]

在調用ls命令的第一過程:

dup2(fd[1],STDOUT_FILENO); 
close(fd[1]); 
execlp(com1, com1, NULL); 

而在第二個孩子的過程,其中調用wc命令:

dup2(fd[0],STDIN_FILENO); 
close(fd[0]); 
execlp(com2, com2, NULL);