问题描述
我有一个关于子进程行为的问题。此测试程序的目的是使用管道运行 Linux 命令 echo Hello | wc
。
预期输出为:
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
,您应该翻转它们。