我正在编写一个运行Linux命令的C程序,如:
$ cat / etc / passwd | cut -f1 -d:|排序
在等待孩子完成时,只有一个孩子成功终止。代码挂起显示“运行排序”
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
int main()
{
int i,fd1[2],fd2[2],status,listpid[3];
pid_t child;
pipe(fd1);
pipe(fd2);
for(i=0; i< 3; i++)
{
printf("\ncreating child\n");
if((child = fork()) == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
else if(child == 0)
{
if(i == 0)
{
close(1); dup(fd1[1]);
close(fd1[0]);
close(fd1[1]);
printf("\nrunning cat /etc/passwd\n");
fflush(stdout);
execlp("cat","cat","/etc/passwd", (char *)NULL);
exit(EXIT_SUCCESS);
}
else if(i == 1)
{
close(0); dup(fd1[0]);
close(fd1[1]);
close(fd1[0]);
close(1); dup(fd2[1]);
close(fd2[1]);
close(fd2[0]);
printf("\nrunning cut -f1 -d:\n");
fflush(stdout);
execlp("cut","cut","-f1","-d:", (char *)NULL);
exit(EXIT_SUCCESS);
}
else if(i == 2)
{
close(0); dup(fd2[0]);
close(fd2[1]);
close(fd2[0]);
close(fd1[0]);
close(fd1[1]);
printf("\nrunning sort\n");
fflush(stdout);
execlp("sort","sort", (char *)NULL);
exit(EXIT_SUCCESS);
}
}
else
{
listpid[i]=child;
}
}
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
close(fd2[1]);
for(i = 0; i < 2; i++)
{
waitpid(listpid[i], &status, 0);
if(WIFEXITED(status))
{
printf("\n[%d] TERMINATED (Status: %d)\n",listpid[i], WEXITSTATUS(status));
}
}
exit(EXIT_SUCCESS);
}
答案 0 :(得分:1)
它“挂起”的原因是因为sort
正在等待更多输入。在输入管道关闭之前,它不会输出任何内容。您的管道可能有问题(您应该检查pipe
和dup
的返回值),但我看不到任何内容。
我的猜测是cut
尚未退出。同样,最可能的原因是它的输入管道没有关闭。那么,它在哪里开放?
它不会在cat
进程中打开,因为没有理由不退出。
它不会在父进程中打开,因为您已仔细关闭所有描述符。
它不会在cut
进程中打开,因为你关闭了fd1的写入结束。
离开sort
进程本身: 仍然打开fd1的描述符!
因此,sort
挂起,因为它等待cut
完成,cut
挂起,因为它等待sort
,即使sort也永远不会向fd1写入任何内容。
你应该关闭第三个孩子的fd1,或者你应该安排每个管子只存在于需要它们的孩子身上。
无论如何,那是我的理论。
答案 1 :(得分:0)
您需要关闭子级2中的管道fd1
,否则子级1将等待更多可能的输入。
另一个问题是,您的waitpid
循环应该有循环条件i < 3
,而不是i < 2
。