Child 进程的奇怪行为

问题描述

我有一个关于子进程行为的问题。此测试程序的目的是使用管道运行 Linux 命令 echo Hello | wc

我的命令不起作用,结果是调用错误的 c 字符串。

预期输出为:

command 0
echo
command 1
wc

但是,我得到:

command 0
echo 
command 1
Hello

当我注释掉时,我只得到预期的输出 execvp(),当子进程没有被退出时。

这里是测试函数

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

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

    // 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 for child processes
            close(pipefd[0]);
            close(pipefd[1]);

            printf("%s\n",*arr[i]);
            //To simply and simulate problem,can replace execvp() with exit(0);
            execvp(*arr[i],arr[i]);
        }
    }
    // Close pipes of parent process    close(pipefd[0]);
    close(pipefd[1]);
    return 0;
}

这里是主要功能

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

    int status;
    
    waitpid(id[0],&status,0); 
    waitpid(id[1],0); 
    return 0;
}

解决方法

printf 写入标准输出,因此它受您的 dup2(pipefd[1],STDOUT_FILENO); 影响,因此进入管道而不是您的屏幕。

您应该改为将诊断消息写入 stderr:

fprintf(stderr,"%s\n",*arr[i]);

您看到 Hello 的原因是这是您反向管道的输出。

wc | echo Hello

如果您想显示 wc 输出 1 1 6,您应该翻转它们。