【问题标题】:c - Can't pipe three processesc - 不能管道三个进程
【发布时间】:2015-02-26 00:07:21
【问题描述】:

我一直在尝试在 c 中实现以下命令: cat /etc/passwd |剪切-f1 -d:|排序

这是我目前得到的代码。第一个管道正常工作,但第二个管道似乎根本不工作。

我一遍又一遍地检查代码,但没有发现任何错误。谁能提供可以解决我的问题的建议?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
    {
        int pipe_A[2];
        int pipe_B[2];

        pipe(pipe_A);
        pipe(pipe_B);

        pid_t pid_A, pid_B, pid_C;

        if( !(pid_A = fork()) ) {
            close(1);       /* close normal stdout */
            dup(pipe_A[1]);   /* make stdout same as pipe_A[1] */
            close(pipe_A[0]); /* we don't need this */
            execlp("/bin/cat", "cat", "/etc/passwd" ,  NULL);
        }

        if( !(pid_B = fork()) ) {
            close(0);       /* close normal stdin */
            dup(pipe_A[0]);   /* make stdin same as pipe_A[0] */
            close(pipe_A[1]); /* we don't need this */

            close(1);   /* close normal stdout */
            dup(pipe_B[1]);   /* make stdout same as pipe_B[1] */
            close(pipe_B[0]); /* we don't need this */
            execlp("/usr/bin/cut", "cut", "-f1", "-d:", NULL);
       }

       if( !(pid_C = fork()) ) {
            close(0);       /* close normal stdin */
            dup(pipe_B[0]);   /* make stdin same as pipe_B[0] */
            close(pipe_B[1]); /* we don't need this */
            execlp("/usr/bin/sort", "sort", NULL);
       }

    return 0;
}

谢谢。

【问题讨论】:

    标签: c process pipe


    【解决方案1】:

    问题是您到处都在泄漏打开的 FD。请注意,每次调用 fork 时,所有打开的管道都会被子进程继承,但带有复制 FD 的管道无法正常工作。

    例如,cat 继承了pipe_B 的读写 FD。同样,sort 继承了pipe_A 的两个 FD。

    正确的做法是(但我建议改用dup2()):

    int main(void)
    {
        int pipe_A[2];
        int pipe_B[2];
        pid_t pid_A, pid_B, pid_C;
    
        pipe(pipe_A);
    
        if( !(pid_A = fork()) ) {
            close(pipe_A[0]); // A-read not needed here
    
            close(1);
            dup(pipe_A[1]);
            close(pipe_A[1]); //do not pass A-write twice
    
            execlp("/bin/cat", "cat", "/etc/passwd" ,  NULL);
        }
    
        close(pipe_A[1]); // A-write not needed anymore
    
        pipe(pipe_B); //do not create this pipe until needed
    
        if( !(pid_B = fork()) ) {
            close(pipe_B[0]); // B-read not needed here
    
            close(0);
            dup(pipe_A[0]);
            close(pipe_A[0]); //do not pass A-read twice
    
    
            close(1);
            dup(pipe_B[1]);
            close(pipe_B[1]); //do not pass B-write twice
    
            execlp("/usr/bin/cut", "cut", "-f1", "-d:", NULL);
       }
       close(pipe_A[0]); // A-read not needed anymore
       close(pipe_B[1]); // B-write not needed anymore
    
       if( !(pid_C = fork()) ) {
    
            close(0);
            dup(pipe_B[0]);
            close(pipe_B[0]); // do not pass B-read twice
    
            execlp("/usr/bin/sort", "sort", NULL);
       }
       close(pipe_B[0]); // B-read not needed anymore
       return 0;
    }
    

    如果您分析我的代码(并且如果我写得对),假设父进程只有 FD 0、1 和 2,那么每个 execlp() 将得到正好 3 个 FD,0、1 和 2。

    【讨论】:

    • 非常感谢您的解释。我会好好阅读代码。我还将尝试实现 dup2() 因为它似乎更适合我一直试图完成的工作。我会投票以表达我的感激之情,但我没有所需的声誉。
    猜你喜欢
    • 1970-01-01
    • 2016-05-05
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 2010-11-20
    相关资源
    最近更新 更多