鉴于任务是使用fork() 和pipe(),您可能需要使用如下算法:
- 父级为其创建管道以写入第一个st 子级。
- 父级保持对第一个st子级的管道写入端打开。
- 父级保持从第 Nth 个子级打开管道的读取端。
- 对于每个孩子 n = 1..N,Parent 为 nth 个孩子创建输出管道以与 n+1th 对话。
- 父分叉 nth 个子节点。
- nth 子级关闭其输入管道的写入端和其输出管道的读取端。
- nth 子进程从输入管道读取 PID 的总和,将自己的 pid 添加到总和中,然后将其写入输出管道,然后退出。
- 同时,Parent 将输入管道的两端关闭到第 nth(除了必须保持打开的描述符),并循环返回以创建第 n+1th sup> 孩子的管道,然后是孩子。
- 当所有子级启动后,父级将其 PID 写入第一个st 子级并关闭该管道的写入端。
- 然后它从第 Nth 个子节点读取响应,关闭管道的读取端,并打印结果。
如何验证总和不太明显,除非每个子节点也将其 PID 写入标准输出,或者父节点(知道所有子节点 PID)计算答案以验证它。
由于完全没有错误检查而获得零分:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int N = (argc > 1) ? atoi(argv[1]) : 10;
int c1_wr;
int cN_rd;
int p1[2];
int p2[2];
int pid_chk = getpid();
if (N <= 0 || N >= 100)
N = 10;
pipe(p1);
c1_wr = dup(p1[1]);
printf("%d children\n", N);
printf("Parent = %d\n", pid_chk);
for (int n = 0; n < N; n++)
{
int pid;
pipe(p2);
fflush(stdout);
if ((pid = fork()) == 0)
{
close(p1[1]);
close(p2[0]);
int pid_sum;
read(p1[0], &pid_sum, sizeof(pid_sum));
pid_sum += getpid();
write(p2[1], &pid_sum, sizeof(pid_sum));
close(p1[0]);
close(p2[1]);
exit(0);
}
printf("Child %2d = %d\n", n+1, pid);
pid_chk += pid;
close(p1[0]);
close(p1[1]);
p1[0] = p2[0];
p1[1] = p2[1];
}
cN_rd = p2[0];
close(p2[1]);
int pid_sum = getpid();
write(c1_wr, &pid_sum, sizeof(pid_sum));
close(c1_wr);
read(cN_rd, &pid_sum, sizeof(pid_sum));
close(cN_rd);
printf("PID sum = %d\n", pid_sum);
printf("PID chk = %d\n", pid_chk);
return 0;
}
示例运行:
10 children
Parent = 49686
Child 1 = 49688
Child 2 = 49689
Child 3 = 49690
Child 4 = 49691
Child 5 = 49692
Child 6 = 49693
Child 7 = 49694
Child 8 = 49695
Child 9 = 49696
Child 10 = 49697
PID sum = 546611
PID chk = 546611
fflush(stdout); 的用途在 (a) 省略它并且 (b) 通过管道运行输出时变得清晰。很有必要。