需要实施此this hierarchy of processes
每个有孩子的过程都不得在孩子面前终止。在
“info()”函数显示的消息条款,a的END消息
父项不应出现在其子项的任何END消息之前。 info函数看起来像这个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,'\0','\0');
info(END,5,0);
// grandchild (of top-level parent)
} else {
waitpid(pid5,'\0','\0');
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,'\0','\0');
info(END,6,0);
}
}
waitpid(pid4,'\0','\0');
waitpid(pid6,'\0','\0');
info(END,3,0);
}
else{
pid8=fork();
if(pid8 == 0){ //P9 child
info(BEGIN,8,0);
info(END,8,0);
}
waitpid(pid2,'\0','\0');
waitpid(pid3,'\0','\0');
waitpid(pid4,'\0','\0');
waitpid(pid5,'\0','\0');
waitpid(pid6,'\0','\0');
waitpid(pid7,'\0','\0');
waitpid(pid8,'\0','\0');
waitpid(pid9,'\0','\0');
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
我试图深入了解这个问题近两个小时,但不能理解什么不顺利,我认为它与waitpid有关,但不能搞清楚......
答案 0 :(得分:0)
最大的问题是你启动了所有这些流程,但你永远不会结束它们。
例如,采用最后一个else
子句。在该块中,您拨打fork
来创建pid8
。然后你有进程8打印BEGIN和END,但是没有退出,它继续进入后续代码,这显然意味着P1(它将毫无意义地调用{{1对于它没有创建的进程)。但是,它会在waitpid
电话中失误。在其他几个代码路径中也会发生同样的事情。
一些建议:
仅在流程中调用info(END,1,0)
,以确切创建为直接子项创建的流程。无论如何,这些是您唯一可以成功呼叫waitpid
的人。例如,P1不能等待它没有创建的P4。
将NULL作为waitpid
的附加参数传递给 waitpid
。 (后者恰好在大多数C实现中都有效,因为字符'\0'
的表示与这些实现中的NULL指针的表示相同,但它不正确:您应该将指针传递给整数[或特殊值'\0'
]不是NULL
值。)
检查系统调用的返回状态。如果你这样做了,你会看到很多char
次呼叫都失败了。 (在这种特殊情况下,实际上并不是造成问题,但检查和打印失败总是一个好主意,因为他们会告诉你为什么程序不是&# 39;按照你的期望工作。)
最重要的是,在每个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 ) {
所有这一切都在同一个短节目中。也就是说,您以不同的方式组合一组基本相同的操作,然后在程序中以不同的间距对它们进行编码。这对编译器没有任何影响,但是对于试图阅读代码的人来说会有很大的不同(如果你编写了足够多的代码,这将包括你自己)。