【问题标题】:Unix Piping using Fork and Dup使用 Fork 和 Dup 的 Unix 管道
【发布时间】:2010-04-07 03:58:10
【问题描述】:

假设在一个程序中我想执行两个进程,一个执行ls -al 命令,然后将结果传送到wc 命令,并在终端上显示输出。如何使用管道文件描述符来做到这一点?到目前为止我写的代码:

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]);
}

举个例子会很有帮助。

【问题讨论】:

    标签: c process pipe unix


    【解决方案1】:

    您的示例代码在语法和语义上被破坏了(例如 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;
    }
    

    【讨论】:

    • 关闭一个dup'd 文件描述符会关闭另一个文件描述符是不是正确的。关闭一个只会删除打开文件的一个句柄。文件本身不会关闭,直到所有dup'd 文件描述符都关闭。
    • 哦,您应该关闭父级中的 pipefd 文件描述符 - 它不需要它们(并且正在阅读的子级不会看到 end-of-文件,直到父级在写入结束时关闭其句柄)。同样,close() 只会删除您传递给它的句柄,底层管道直到 所有 的句柄在 每个 进程中都关闭后才会关闭.
    • 您最后的评论是否正确?他们不是一个父母的孩子吗?
    • 我们可以在这里摆脱close吗?
    猜你喜欢
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    • 2014-05-12
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多