子进程未在管道中退出 [英] Child Process not exiting in Piping

查看:70
本文介绍了子进程未在管道中退出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

这是代码的假设输出:

命令 0命令 0 应该退出命令 11 1 6

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

命令 0命令 0 应该退出命令 1

<预><代码>int 测试(pid_t id[]){国际我;int pipefd[2];char *cat_args[] = {echo",Hello", NULL};char *grep_args[] = {wc",NULL};//做一个管道管道(pipefd);for(i = 0; i <2; i++){id[i] = fork();如果 (id[i] == -1){printf("无法创建子进程");fprintf(stderr,fork() 未能生成子进程");退出(1);}否则如果(id [i] == 0){printf("命令");printf("%d\n",i);如果(我== 0){dup2(pipefd[0],STDIN_FILENO);}否则如果(我== 1){dup2(pipefd[1],STDOUT_FILENO);}//关闭管道关闭(pipefd[0]);关闭(pipefd [1]);如果(我== 1){execvp(*cat_args,cat_args);//正常退出(0)}否则如果(我== 0){printf(命令 0 应该退出\n");execvp(*grep_args,grep_args);printf(命令 0 退出\n");//如果第一个孩子退出,应该打印出来}}}返回0;}

这里是主要功能:

<预><代码>int main(int argc, char **argv){pid_t id[2];测试(ID);内部状态;//如果取消注释,则永远不会运行管道 Linux 命令//并且 main() 永远不会退出//waitpid(id[0],&status,0);waitpid(id[1],&status,0);//这有效返回0;}

谢谢.

解决方案

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

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

顺便说一句,您的 printf("command 0 exited\n") 没有用,因为在成功 execvp() 之后什么也没有执行.

I'm currently testing a program that executes the Linux command echo Hello | wc using piping.

The parent process in main() spawns two child processes, the first one which executes echo Hello, and the second one which executes wc. These two processes communicate via a pipe.

However, when I call waitpid() on the two child processes, only the second process exits. The first process successfully runs execvp(), but hangs there.

Here is the supposed output of the code:

command 0
command 0 should exit
command 1
      1       1       6

If I uncommment the line waitpid(id[0],&status,0); then the output is

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

Here is the main function:


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

Thank you.

解决方案

The sub-process running wc hangs because the pipe is still readable despite the sub-process running echo Hello died. wc still waits for something to read through the pipe.

Why is the pipe still readable? Because you didn't close it in the parent process, the one that does the two forks. Therefore, the parent can still read and write to the pipe and the wc sub-process stays blocked on read() and never receives an EOF.

BTW, your printf("command 0 exited\n") is useless since nothing is executed after a successful execvp().

这篇关于子进程未在管道中退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆