2015-06-13 40 views
2

我試圖做一個程序,執行下面的命令,將一個輸出連接到下一個使用管道的輸入並帶兩個參數DIR(directory)和ARG(文件類型,例如:jpg)。程序卡在管道上(執行ls grep排序)

ls DIR -laR | grep ARG |排序

下面的代碼:

int main(int argc, char *argv[]) { 

    if (argc != 3) { 
     printf("Invalid arguments. <dir> <arg>\n"); 
     exit(1); 
    } 

    int pipe_fd1[2]; 
    int pipe_fd2[2]; 
    pid_t ls_pid, grep_pid; 
    int status; 

    pipe(pipe_fd1); 
    pipe(pipe_fd2); 

    ls_pid = fork(); 
    if (ls_pid == 0) { //first child ls DIR -laR 
     dup2(pipe_fd1[1], STDOUT_FILENO); 
     close(pipe_fd1[0]); 

     execlp("ls", "ls", argv[1], "-laR", NULL); 

    } else if (ls_pid > 0) { 
     grep_pid = fork(); 
     if (grep_pid == 0) { //second child grep ARG 
      dup2(pipe_fd1[0], STDIN_FILENO); 
      dup2(pipe_fd2[1], STDOUT_FILENO);  
      close(pipe_fd1[1]); 
      close(pipe_fd2[0]); 

      waitpid(ls_pid, &status, 0);  
      execlp("grep", "grep", argv[2], NULL); 

     } else if (grep_pid > 0) { //parent sort 
      dup2(pipe_fd2[0], STDIN_FILENO); 
      close(pipe_fd2[1]); 

      waitpid(grep_pid, &status, 0); 
      execlp("sort", "sort", NULL); 
     } 

    } 

    return 0; 
} 

它似乎被卡住?不知道爲什麼?

+0

你爲什麼要等待'grep'調用'sort'之前終止? – fuz

+0

在我的系統上,程序停留在'waitpid(grep_pid,&status,0)'行;''grep'永遠不會終止。爲什麼不關閉父進程中與第一個管道關聯的文件描述符? – fuz

回答

3

你父從未接近pipe_fd1,所以grepsort doen't知道何時停止讀取輸入:因爲管道讀取和寫入端永遠不會關閉父,讀者塊等待更多的輸入,將永遠到達。你需要關閉它。

此外,您不需要waitpid():管道的工作方式可確保輸入線性流動並按順序在整個管道中流動。

下面是這些問題的工作版本解決:

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

int main(int argc, char *argv[]) { 

    if (argc != 3) { 
     printf("Invalid arguments. <dir> <arg>\n"); 
     exit(1); 
    } 

    int pipe_fd1[2]; 
    int pipe_fd2[2]; 
    pid_t ls_pid, grep_pid; 

    pipe(pipe_fd1); 

    ls_pid = fork(); 
    if (ls_pid == 0) { //first child ls DIR -laR 
     dup2(pipe_fd1[1], STDOUT_FILENO); 
     close(pipe_fd1[0]); 
     execlp("ls", "ls", argv[1], "-laR", NULL); 

    } else if (ls_pid > 0) { 
     dup2(pipe_fd1[0], STDIN_FILENO); 
     close(pipe_fd1[1]); 

     pipe(pipe_fd2); 
     grep_pid = fork(); 

     if (grep_pid == 0) { //second child grep ARG 
      dup2(pipe_fd2[1], STDOUT_FILENO); 
      close(pipe_fd2[0]); 
      execlp("grep", "grep", argv[2], NULL); 

     } else if (grep_pid > 0) { //parent sort 
      dup2(pipe_fd2[0], STDIN_FILENO); 
      close(pipe_fd2[1]); 
      execlp("sort", "sort", NULL); 
     } 

    } 

    return 0; 
} 
+0

感謝您的幫助,但我不明白爲什麼當父母不使用'pipe_fd1'執行任何重定向時父爲什麼需要關閉'pipe_fd1'。 – 0kazaki

+0

@ 0kazaki因爲只要管道中至少有一個作者,讀者進程就永遠不會看到輸入結束,即使該作者(父)沒有真正寫入。當最後一位作家關閉管道時,讀者將會看到輸入結束並繼續進行('sort'需要在顯示結果之前消耗所有的輸入)。 –