需要实现这个进程层次结构
每个具有子进程的进程都不得在其子进程之前终止。在 由"info(("函数显示的消息项,一个 父级不应出现在其子级的任何 END 消息之前。信息函数如下所示info(BEGIN | END, process_no, thread_no);
int main() {
init();
pid_t pid2, pid3, pid4,pid5,pid6,pid7,pid8,pid9;
info(BEGIN,1,0);
pid2 = fork();
if ( pid2 == 0 ) {
// P2 child
info(BEGIN,2,0);
pid5 = fork();
if ( pid5 == 0 ) { // P5 child
info(BEGIN,5,0);
pid9 = fork();
if(pid9 == 0){ // P9 child
info(BEGIN,9,0);
info(END,9,0);
}
waitpid(pid9,' ',' ');
info(END,5,0);
// grandchild (of top-level parent)
} else {
waitpid(pid5,' ',' ');
info(END,2,0);
}
} else if((pid3 = fork()) == 0) {
info(BEGIN,3,0); // P3 child
pid4 = fork();
if(pid4 == 0){ //P4 child
info(BEGIN,4,0);
info(END,4,0);
}else{
pid6 = fork();
if(pid6 == 0){ //P6 child
info(BEGIN,6,0);
pid7 = fork();
if(pid7 == 0){ //P7 child
info(BEGIN,7,0);
info(END,7,0);
}
waitpid(pid7,' ',' ');
info(END,6,0);
}
}
waitpid(pid4,' ',' ');
waitpid(pid6,' ',' ');
info(END,3,0);
}
else{
pid8=fork();
if(pid8 == 0){ //P9 child
info(BEGIN,8,0);
info(END,8,0);
}
waitpid(pid2,' ',' ');
waitpid(pid3,' ',' ');
waitpid(pid4,' ',' ');
waitpid(pid5,' ',' ');
waitpid(pid6,' ',' ');
waitpid(pid7,' ',' ');
waitpid(pid8,' ',' ');
waitpid(pid9,' ',' ');
info(END, 1, 0);
}
for(int i=0; i<8; i++){
wait(NULL);
}
return 0;
}
我的输出是
[ ] BEGIN P1 T0 pid=4370 ppid=4122 tid=1184286464
[ ] BEGIN P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ] BEGIN P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P3 T0 pid=4372 ppid=4370 tid=1184286464
[ ] END P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P5 T0 pid=4374 ppid=4371 tid=1184286464
[ ] END P1 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P6 T0 pid=4376 ppid=4372 tid=1184286464
[ ] END P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ] END P3 T0 pid=4375 ppid=4372 tid=1184286464
[ ] END P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ] BEGIN P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ] END P5 T0 pid=4377 ppid=4374 tid=1184286464
[ ] END P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ] END P6 T0 pid=4378 ppid=4376 tid=1184286464
[ ] END P5 T0 pid=4374 ppid=4371 tid=1184286464
[ ] END P3 T0 pid=4378 ppid=4376 tid=1184286464
[ ] END P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ] END P6 T0 pid=4376 ppid=4372 tid=1184286464
[ ] END P3 T0 pid=4376 ppid=4372 tid=1184286464
[ ] END P3 T0 pid=4372 ppid=4370 tid=1184286464
[ ] END P1 T0 pid=4370 ppid=4122 tid=1184286464
预期输出 :
[ ] BEGIN P1 T0 pid=4370 ppid=4122 tid=1184286464
[ ] BEGIN P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ] BEGIN P3 T0 pid=4372 ppid=4370 tid=1184286464
[ ] BEGIN P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] END P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P5 T0 pid=4374 ppid=4371 tid=1184286464
[ ] BEGIN P6 T0 pid=4376 ppid=4372 tid=1184286464
[ ] END P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ] END P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ] BEGIN P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ] END P5 T0 pid=4377 ppid=4374 tid=1184286464
[ ] END P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ] END P6 T0 pid=4378 ppid=4376 tid=1184286464
[ ] END P3 T0 pid=4378 ppid=4376 tid=1184286464
[ ] END P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ] END P1 T0 pid=4370 ppid=4122 tid=1184286464
我试图深入了解这个问题将近 2 个小时,但无法理解进展不顺利的地方,我认为这与 waitpid 有关,但无法弄清楚......
最大的问题是你开始了所有这些过程,但你永远不会结束它们。
以最后一个else
子句为例。在该块中,您调用 fork
来创建pid8
。然后,进程 8 打印 BEGIN 和 END,但随后它不会退出,而是继续进入后续代码,这显然是针对 P1 的(它将毫无意义地为它未创建的进程调用 waitpid
(。而且,它会在info(END,1,0)
电话中失误。在其他几个代码路径中也会发生同样的事情。
几点建议:
-
仅在进程中为作为直接子级创建的那些进程调用
waitpid
。无论如何,这些是您唯一可以成功调用waitpid
的。例如,P1 不能等待它未创建的 P4。 -
将 NULL 作为附加参数传递给
waitpid
而不是' '
。(后者恰好在大多数 C 实现中工作,因为字符' '
的表示形式与这些实现中 NULL 指针的表示形式相同,但它不正确:您应该传递指向整数 [或特殊值NULL
] 的指针,而不是char
值。 -
检查系统呼叫的返回状态。如果您这样做,您会发现许多
waitpid
呼叫失败。(在这种特殊情况下,这实际上并不会导致问题,但是检查并打印出故障始终是一个好主意,因为它们会提示您为什么程序没有按预期工作。 -
最重要的是,在每个
if (pidX == 0) {
子句中,在执行该块应该执行的其他任何操作后,放置一个exit(0)
语句以使进程退出:pid8=fork(); if(pid8 == 0){ info(BEGIN,8,0); info(END,8,0); exit(0); /* <<<<<<============ */ }
最后的建议: 选择一种编码风格并坚持下去。你有
pid8=fork();
if(pid8 == 0){
而你有
pid2 = fork();
if ( pid2 == 0 ) {
而你有
if((pid3 = fork()) == 0) {
所有这些都在同一个简短的程序中。也就是说,您以不同的方式组合一组基本相同的操作,然后以不同的间距在程序中对它们进行编码。这对编译器没有任何影响,但对于试图阅读代码的人(如果你写了足够的代码,这将包括你自己(有很大的不同。