gpt4 book ai didi

c - Unix 进程 fork 层次结构

转载 作者:行者123 更新时间:2023-11-30 16:32:32 25 4
gpt4 key购买 nike

需要实现这个this hierarchy of processes

每个有子进程的进程都不能在其子进程之前终止。在就“info()”函数显示的消息而言,父级永远不应该出现在其子级的任何 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

我花了近 2 个小时试图弄清楚这一点,但无法理解什么地方进展不顺利,我认为这与 waitpid 有关,但无法弄清楚......

最佳答案

最大的问题是您启动了所有这些进程,但从未结束它们。

以最后一个 else 子句为例。在该 block 中,您调用 fork 来创建 pid8。然后进程 8 打印 BEGIN 和 END,但随后它不退出,它继续进入后续代码,这显然是针对 P1 的(在那里它将毫无意义地调用 waitpid 对于它没有创建的进程)。而且,它还会在 info(END,1,0) 调用中出错。同样的事情也发生在其他几个代码路径中。

一些建议:

  1. 仅在进程中为那些作为直接子进程创建的进程调用 waitpid。无论如何,只有这些是您可以成功调用 waitpid 的。例如,P1 无法等待 P4,因为 P4 不是它创建的。

  2. 将 NULL 作为附加参数传递给 waitpid 而不是 '\0'。 (后者恰好适用于大多数 C 实现,因为字符 '\0' 的表示形式与这些实现中 NULL 指针的表示形式相同,但它是不正确的:您应该传递一个指向整数的指针[或特殊值NULL]而不是char值。)

  3. 检查系统调用的返回状态。如果您这样做了,您会发现许多 waitpid 调用都失败了。 (在这种特殊情况下,这实际上并不是导致问题,但检查并打印出失败总是一个好主意,因为它们会提示您为什么程序无法按照您的方式运行期待。)

  4. 最重要的是,在每个 if (pidX == 0) { 子句中,在执行该 block 应该执行的其他操作后,放置一个 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) {

所有这些都在同一个短节目中。也就是说,您以不同的方式组合一组本质上相同的操作,然后在程序中以不同的间距对它们进行编码。这对编译器没有任何影响,但对于试图阅读你的代码的人来说却有很大的不同(如果你编写了足够的代码,这也包括你自己)。

关于c - Unix 进程 fork 层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50104337/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com