我正在尝试创建三个子进程和两个将执行三个execlp()
的管道。但是,当我的程序运行时,输出不是我所期望的。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
pid_t pid = getpid();
printf("STARTING PROCESSXXX %d\n",pid);
int c1Toc2[2];
int c2Toc3[2];
if(pipe(c1Toc2) == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
if(pipe(c2Toc3) == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
int rValue = fork();
if(rValue == -1)
{
perror("Child_1");
}
else if (rValue == 0)
{
printf("CHILD 1: ");
printf("PROCESS ID IS: %ld \tMY PARENT ID IS: %ld\trValue IS: %d\n", (long) getpid(), (long) getppid(), rValue);
dup2(c1Toc2[1], STDOUT_FILENO);
close(c1Toc2[0]);
close(c2Toc3[0]);
execlp("ps", "ps", "-ef", NULL);
exit(0);
}
rValue = fork();
if(rValue == -1)
{
perror("Child_2");
}
else if (rValue == 0)
{
printf("CHILD 2: ");
printf("PROCESS ID IS: %ld \tMY PARENT ID IS: %ld\trValue IS: %d\n",
(long) getpid(), (long) getppid(), rValue);
dup2(c1Toc2[0], STDIN_FILENO);
close(c1Toc2[1]);
dup2(c2Toc3[1], STDOUT_FILENO);
close(c2Toc3[0]);
printf("CHILD 2 : goodbye\n");
execlp("grep","grep","root",NULL);
printf("CHILD 2 : goodbye\n");
exit(0);
}
rValue = fork();
if(rValue == -1)
{
perror("Child_3");
}
else if (rValue == 0)
{
printf("CHILD 3: ");
printf("PROCESS ID IS: %ld \tMY PARENT ID IS: %ld\trValue IS: %d\n",
(long) getpid(), (long) getppid(), rValue);
dup2(c2Toc3[0], STDIN_FILENO);
close(c2Toc3[1]);
close(c2Toc3[0]);
printf("CHILD 3 : \n");
execlp("sort","sort","-n", "-k4",NULL);
printf("CHILD 3 : goodbye\n");
exit(0);
}
close(c1Toc2[1]);
close(c1Toc2[0]);
close(c2Toc3[1]);
close(c2Toc3[0]);
// Add the code for the two children here
sleep(3);
printf("PARENT: PROCESS Waiting on children to complete\n");
printf("Final Print Statement before exit\n");
exit(0);
}
答案 0 :(得分:0)
问题是你没有关闭子文件中的管道文件描述符,因此,你将它们复制到STDOUT_FILENO(例如 - grep child),即使程序已完成其常规输出,它也没有'完全退出并将EOF发布到下一个子进程(即 - 排序),这样这些孩子就会一直等待着。
我不完全确定为什么你的grep进程拒绝像正常一样退出,因为它看起来似乎是ps子退出,这应该将一个EOF发布到grep child的stdin。
这是一个可以满足您需求的版本:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
pid_t pid = getpid();
printf("PARENT: STARTING PROCESSXXX %d\n",pid);
int c1Toc2[2];
int c2Toc3[2];
if (pipe(c1Toc2) == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
if (pipe(c2Toc3) == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
int rValue = fork();
if (rValue == -1)
{
perror("Child_1");
exit(EXIT_FAILURE);
}
else if (rValue == 0)
{
printf("CHILD 1: PROCESS ID IS: %ld \tMY PARENT ID IS: %ld\trValue IS: %d\n", (long) getpid(), (long) getppid(), rValue);
dup2(c1Toc2[1], STDOUT_FILENO);
close(c1Toc2[0]);
close(c1Toc2[1]);
close(c2Toc3[0]);
close(c2Toc3[1]);
execlp("ps", "ps", "-ef", NULL);
perror("CHILD 1: execlp");
exit(EXIT_FAILURE);
}
rValue = fork();
if (rValue == -1)
{
perror("Child_2");
exit(EXIT_FAILURE);
}
else if (rValue == 0)
{
printf("CHILD 2: PROCESS ID IS: %ld \tMY PARENT ID IS: %ld\trValue IS: %d\n", (long) getpid(), (long) getppid(), rValue);
dup2(c1Toc2[0], STDIN_FILENO);
dup2(c2Toc3[1], STDOUT_FILENO);
close(c1Toc2[0]);
close(c1Toc2[1]);
close(c2Toc3[0]);
close(c2Toc3[1]);
execlp("grep","grep","root",NULL);
perror("CHILD 2: execlp");
exit(EXIT_FAILURE);
}
rValue = fork();
if (rValue == -1)
{
perror("Child_3");
exit(EXIT_FAILURE);
}
else if (rValue == 0)
{
printf("CHILD 3: PROCESS ID IS: %ld \tMY PARENT ID IS: %ld\trValue IS: %d\n", (long) getpid(), (long) getppid(), rValue);
dup2(c2Toc3[0], STDIN_FILENO);
close(c1Toc2[0]);
close(c1Toc2[1]);
close(c2Toc3[0]);
close(c2Toc3[1]);
execlp("sort","sort","-n", "-k4",NULL);
perror("CHILD 3: execlp");
exit(EXIT_FAILURE);
}
close(c1Toc2[0]);
close(c1Toc2[1]);
close(c2Toc3[0]);
close(c2Toc3[1]);
printf("PARENT: PROCESS Waiting on children to complete\n");
sleep(3);
printf("PARENT: Final Print Statement before exit\n");
return 0;
}
答案 1 :(得分:0)
您的代码看起来或多或少是正确的,但它似乎反映了对fork / exec和子进程管理的不完全理解。
首先,请注意除了失败之外,exec-family函数(包括execlp()
)不会返回。您的代码似乎另有假设。特别是,子流程不打印&#34;再见&#34;调用execlp()
后的消息,除非execlp()
调用失败。您应该处理execlp()
确实返回的(失败)情况,但通常您会使用错误处理/错误报告代码来执行此操作。
此外,每个进程(包括父进程)都应该关闭它不会使用的文件描述符。这包括在将FD复制到其中一个标准文件号之后关闭FD,并关闭专门用于其他进程的所有文件描述符。你错过了其中几个:
c1Toc2[1]
(复制后)和c2Toc3[1]
。c1Toc2[0]
和c2Toc3[1]
(复制后)。此外,sleep()
的父进程等待其子进程是没有意义的。如果要确保完成和/或获取退出状态,则应使用wait()
或waitpid()
。如果它不会立即退出,那么它肯定应该使用其中一个函数,否则子进程将作为僵尸进程挂起,直到父进程退出。没有任何数量的sleep()
足以确保子进程完成。另一方面,如果你不关心任何这些事情,那么你可以让父母离开。在这种情况下保持它没有特别的优势。
我不知道是否有任何一种解释了您所看到的意外行为,因为您还没有解释这是什么。