在C linux中使用fork管道两次

时间:2013-01-11 23:56:18

标签: c linux ubuntu pipe systems-programming

我正在尝试重写像ls | wc | wc那样的ac程序,我已经为ls | wc做了它,它工作正常,但我无法弄清楚为什么我的程序在指示的孩子停止线。请帮忙!

int main (void)
{
    pid_t pid_fils, pid_pfils;

    int fd[2], fd2[2];

    if(pipe(fd)==-1 || pipe(fd2)==-1)
    {
        printf("pipe failed!");
        return 1;
    }

    printf("program started\n");
    pid_fils=fork();
    if(pid_fils==0)
    {
        pid_pfils=fork();
        if(pid_pfils==0)
        {
            //action3
            printf("I am the grandson\n");
            close(fd[0]);//close read side
            dup2(fd[1],1);//connect write with stdout
            close(fd[1]);//close write side
            execlp("ls","ls",(char*)0);
            //execvp("ls",argv3);
            return 0;/*actions grandson*/
        }
        else
        {
            //action2
            printf("I am the son\n");
            wait();
            printf("son, wait ok\n");
            >close(fd[1]);  //close read side
            >dup2(fd[0],0); //connect write with stdin
            >close(fd[0]);  //close read side

            ///////pipe2////
           > close(fd2[0]);  //close read side
            >dup2(fd2[1],1); //connect write with stdout/*it stops here -can't display "ok!"*/
            printf("ok!\n");    
            >close(fd2[1]);  //close write side

            execlp("wc","wc",(char*)0);
            printf("error exec returned!\n");    
            return 0;
        }
    }
    else
    {
        ///action1
        printf("I am the parent\n");
        wait();
        printf("parent,wait ok\n");
        close(fd2[1]);  //close write side, 
        dup2(fd2[0],0); //connect read with stdin
        close(fd2[0]);  //close read side
        execlp("wc","wc",(char*)0);
        return 0;/*the parent*/
    }
    return 1;
}

2 个答案:

答案 0 :(得分:3)

确保关闭所有未使用的描述符。在您的情况下,最简单的解决方案是将管道(fd)的创建移动到第一个if块(在第一个子流程中)。问题是只要任何进程可能写入管道,读者就不会获得EOF,因此不会终止。

if(pipe(fd2)==-1)
{
    printf("pipe failed!");
    return 1;
}

printf("program started\n");
pid_fils=fork();
if(pid_fils==0)
{
    if(pipe(fd)==-1)
    {
        printf("pipe failed!");
        return 1;
    }
    pid_pfils=fork();

我还应该提一下,你可能想重新考虑等待电话。不确定你打算用它们做什么,但你不希望“ls”进程阻止输出,因为读者尚未启动。

答案 1 :(得分:1)

dup2(fd2[1],1);

上面一行将首先关闭描述符1处的文件,然后将fd2 [1]中的描述符复制为1。

1是标准输出。意思是调用关闭stdout。

printf打印到stdout,意味着printf打印到1,现在分配给管道fd2

所以你的确定进入了管道,而不是在屏幕上。

        //action2
        printf("I am the son\n");
        wait();
        printf("son, wait ok\n");
        close(fd[1]);  //close read side
        dup2(fd[0],0); //connect write with stdin
        close(fd[0]);  //close read side

        ///////pipe2////
        int my_terminal_out = dup(1);
        close(fd2[0]);  //close read side
        dup2(fd2[1],1); //connect write with stdout/*it stops here -can't display "ok!"*/
        fprintf(my_terminal_out, "ok!\n");    
        close(fd2[1]);  //close write side

未经测试。此外,您应该测试其余代码是否存在类似的失误。

+ DrC说的话。