我目前正在测试一个使用管道执行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("%dn",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 exitn");
execvp(*grep_args,grep_args);
printf("command 0 exitedn"); //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
的子进程挂起,因为尽管运行echo Hello
的子进程已死亡,但管道仍然可读。wc
仍在等待通过管道读取的内容。
为什么管道仍然可读?因为您没有在执行两个fork
s的父进程中关闭它。因此,父进程仍然可以对管道进行读写,而wc
子进程在read()
上保持阻塞状态,并且从未接收到EOF。
顺便说一句,你的printf("command 0 exitedn")
是无用的,因为成功的execvp()
之后什么都不执行。