2010-04-07 48 views
2

可以说我的程序中我想执行两个子进程,一个执行“ls -al”命令,然后将其传送到“wc”命令并在终端上显示输出。我怎样才能做到这一点使用管道文件描述符到目前为止,我写的代码:一个例子是大大有益的使用fork和dup的Unix管道

int main(int argc, char *argv[]) { 
    int pipefd[2]; 
    int pipefd2[2]; 

    pipe(pipefd2); 
    if ((fork()) == 0) { 
     dup2(pipefd2[1],STDOUT_FILENO); 
     close(pipefd2[0]); 
     close(pipefd2[1]); 
     execl("ls", "ls","-al", NULL); 
     exit(EXIT_FAILURE); 
    } 

    if ((fork()) == 0){ 
     dup2(pipefd2[0],STDIN_FILENO); 
     close(pipefd2[0]); 
     close(pipefd2[1]); 
     execl("/usr/bin/wc","wc",NULL); 
     exit(EXIT_FAILURE); 
    } 
    close(pipefd[0]); 
    close(pipefd[1]); 
    close(pipefd2[0]); 
    close(pipefd2[1]); 
} 

回答

10

你的示例代码是语法和语义损坏(如pipefd2不decared,pipefd和pipefd2之间的混淆,等等)由于这种味道像家庭作业,请确保您了解我的注释,并询问更多您是否需要。我已经忽略了对pipe,fork和dup的错误检查,但理想情况下它们应该在那里。

int main(int argc, char *argv[]) { 
    int pipefd[2]; 
    pid_t ls_pid, wc_pid; 

    pipe(pipefd); 

    // this child is generating output to the pipe 
    // 
    if ((ls_pid = fork()) == 0) { 
     // attach stdout to the left side of pipe 
     // and inherit stdin and stdout from parent 
     dup2(pipefd[1],STDOUT_FILENO); 
     close(pipefd[0]);    // not using the right side 

     execl("/bin/ls", "ls","-al", NULL); 
     perror("exec ls failed"); 
     exit(EXIT_FAILURE); 
    } 

    // this child is consuming input from the pipe 
    // 
    if ((wc_pid = fork()) == 0) { 
     // attach stdin to the right side of pipe 
     // and inherit stdout and stderr from parent 
     dup2(pipefd[0], STDIN_FILENO); 

     close(pipefd[1]);    // not using the left side 
     execl("/usr/bin/wc", "wc", NULL); 
     perror("exec wc failed"); 
     exit(EXIT_FAILURE); 
    } 

    // explicitly not waiting for ls_pid here 
    // wc_pid isn't even my child, it belongs to ls_pid 

    return EXIT_SUCCESS; 
} 
+1

关闭一个'dup''d文件描述符关闭另一个是**不是**。关闭只是删除打开文件的一个句柄。文件本身在所有的'dup''d文件描述符都关闭之前不会关闭。 – caf 2010-04-07 07:42:10

+1

哦,你*应该关闭父文件中的'pipefd'文件描述符 - 它不需要它们(并且直到父文件在写入结束时关闭它的句柄,阅读子文件才会看到文件结束) 。同样,'close()'只能删除你传递它的句柄,直到* every *进程中的所有句柄都关闭,底层管道才会关闭。 – caf 2010-04-07 07:49:35

+1

你是多么的正确,咖啡,更正,谢谢。 – msw 2010-04-07 12:33:42