【问题标题】:Child Process not exiting in Piping [duplicate]子进程未在管道中退出[重复]
【发布时间】:2021-07-03 13:44:35
【问题描述】:

我目前正在测试一个使用管道执行 Linux 命令echo Hello | wc 的程序。

main() 中的父进程生成两个子进程,第一个执行echo Hello,第二个执行wc。这两个进程通过管道进行通信。

但是,当我在两个子进程上调用 waitpid() 时,只有第二个进程退出。第一个进程成功运行execvp(),但挂在那里。

这是代码的假定输出:

command 0
command 0 should exit
command 1
      1       1       6

如果我取消注释行 waitpid(id[0],&status,0); 那么输出是

command 0
command 0 should exit
command 1

int test(pid_t id[])
{
    int i;
    int pipefd[2];

    char *cat_args[] = {"echo","Hello", NULL};
    char *grep_args[] = {"wc", NULL};

    // make a pipe
    pipe(pipefd);

    for(i = 0; i < 2; i++){
        id[i] = fork();

        if (id[i] == -1){
            printf("Unable to create child process");
            fprintf(stderr,"fork() failed to spawn child process");
            exit(1);
        }
        else if (id[i] == 0){
            printf("command ");
            printf("%d\n",i);
            
            if (i == 0){
                dup2(pipefd[0],STDIN_FILENO);
            }
            else if (i == 1){
                dup2(pipefd[1],STDOUT_FILENO);
            }

            // Close pipes
            close(pipefd[0]);
            close(pipefd[1]);

            if (i == 1){
                execvp(*cat_args,cat_args); //exit(0) normally
            }
            else if (i == 0){
                printf("command 0 should exit\n");
                execvp(*grep_args,grep_args); 
                printf("command 0 exited\n"); //If first child exits, should print it out
            }
            
        }
    }
    return 0;
}

这里是主要功能:


int main(int argc, char **argv)
{ 
    pid_t id[2];
    test(id);

    int status;
    
    // If this is uncommented, the piped Linux command is never ran
    // and main() never exits
    //waitpid(id[0],&status,0); 

    waitpid(id[1],&status,0); // This works
    return 0;
}

谢谢。

【问题讨论】:

  • 您的评论不正确。如果取消注释该行,wc 命令会执行,但它永远不会完成,因此永远不会打印任何数据(它的输出缓冲区永远不会被刷新)。如果您留下注释行,wc 命令只会终止,因为父级退出并且其所有文件描述符都已关闭。

标签: c linux pipe execvp


【解决方案1】:

运行wc 的子进程挂起,因为尽管运行echo Hello 的子进程死亡,管道仍然可读。 wc 仍在等待通过管道读取某些内容。

为什么管道仍然可读?因为您没有在父进程中关闭它,所以执行两个forks 的那个。因此,父进程仍然可以读取和写入管道,wc 子进程在read() 上保持阻塞状态,并且永远不会收到 EOF。

顺便说一句,您的printf("command 0 exited\n") 没有用,因为在成功execvp() 之后没有执行任何操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-04
    • 2018-08-04
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 2013-08-01
    • 1970-01-01
    相关资源
    最近更新 更多