首页 > 解决方案 > 在 C 中,为什么我的程序在尝试管道多个命令时卡在 wait() 上?

问题描述

我正在编写一个简单的程序来在三个命令之间进行管道传输。对于每个命令,我 fork 一个子节点并在其中调用 execvp,而父节点等待 execvp 完成(注意因为我 fork 3 次,所以我调用 wait(NULL) 3 次)

我创建了两个管道,pipe_A 和 pipe_Z。流程类似于:

命令 1 将其输出写入 pipe_A,命令 2 从 pipe_A 读取输入,然后将输出写入 pipe_Z,然后命令 3 从 pipe_Z 读取输入,然后写入标准输出。

问题是程序卡在第二个等待(NULL)上。在我的代码中,它是 'printf("reached\n");' 之后的行。程序不会终止,并且在我发送中断之前一直卡住。

如果我用相同的命令“echo hello”替换所有三个命令,它不会做太多,但程序至少会结束。

我编写了一个较小的程序(相同的结构),只有两个命令(“echo hello”和“wc”),它也卡住了,就在第一次等待(NULL)。但是,我注意到,如果我在主程序的第二个命令上调用 execvp,输出会按预期打印。但是,程序也会立即终止(因为 execvp),所以这不是我想要的方式。

我怀疑我犯了一个非常明显的错误,因为缺乏对管道如何工作或 wait(NULL) 函数调用如何工作的理解。

诠释主要(){

//### COMMANDS AS STRING ARRAYS ###

    char * cmds1[3] = {"echo","hello", NULL};
    char * cmds2[3] = {"cat","-",NULL};
    char * cmds3[3] = {"wc", NULL};

//### CREATING PIPES ###

    int pipe_A[2];
    int pipe_Z[2];

    pipe(pipe_A);
    pipe(pipe_Z);

//### FIRST FORK FOR FIRST EXECVP ###

    int pid = fork();

    //Child process
    if(pid==0){

        close(pipe_A[0]);
        dup2(pipe_A[1], STDOUT_FILENO);

        execvp(cmds1[0],cmds1);
        exit(1);

    }

    //Parent process
    else if(pid >0){
        wait(NULL);
    }

//### SECOND FORK FOR SECOND EXECVP ###

    int pid2 = fork();

    //Child process
    if(pid2==0){

        close(pipe_A[1]);
        dup2(pipe_A[0],STDIN_FILENO);

        close(pipe_Z[0]);
        dup2(pipe_Z[1], STDOUT_FILENO); 

        execvp(cmds2[0],cmds2);
        exit(1);

    }

    //Parent process
    else if(pid2>0){

        printf("reached\n");
        wait(NULL);

    }

//### THIRD FORK FOR THIRD EXECVP ###

    int pid3 = fork();

    //Child process
    if(pid3==0){

        close(pipe_Z[1]);
        dup2(pipe_Z[0],STDIN_FILENO);

        execvp(cmds3[0],cmds3);
        exit(1);

    }

    //Parent process
    else if(pid2 >0){

        wait(NULL);

    }


//### END OF PROGRAM ###

    return 0;

}

预期输出为“1 1 6”,但程序不会终止。

标签: cpipefork

解决方案


您没有关闭父进程中管道的写端,所以它们都没有真正关闭,所以没有一个子进程得到 EOF,所以没有一个子进程(除了echo不读取输入)永远退出。


推荐阅读