如何让子进程等待孙子进程?

How to make child process to wait grandchild process?

我试图让一个进程创建 x 个子进程,并且每个子进程创建 y 个子进程。当 x=2, y=2

时看起来像这样

这是我到目前为止所做的,

    pid_t managers[x];
    pid_t workers[y];

    for (int i = 0; i < x; i++) {
        if (i == 0)  // create first manager process
            managers[i] = fork();
        else if (managers[i - 1] > 0)
            managers[i] = fork();
        if (managers[i] == 0)
            for (int j = 0; j < y; j++) {
                if (j == 0)  // create first worker process
                    workers[j] = fork();
                else if (workers[j - 1] > 0)
                    workers[j] = fork();
            }
        // manager process waiting for worker process?
        for (int j = 0; j < y; j++)
            wait(NULL);
    }
    // director process waiting for manager process?
    for (int i = 0; i < x; i++)
        wait(NULL);

    for (int i = 0; i < x; i++)
        printf("managers[%d] = %d\n", i, managers[i]);


当我 运行 这段代码 x=2, y=2 时,最后一个 printf 函数打印了这个,

managers[0] = 0
managers[1] = 0
managers[0] = 0
managers[0] = 0
managers[1] = 0
managers[1] = 0
managers[0] = 0
managers[1] = 0
managers[0] = 0
managers[1] = 0
managers[0] = 0
managers[1] = 0
managers[0] = 0
managers[1] = 0
managers[0] = 0
managers[1] = 0
managers[0] = 0
managers[1] = 0
managers[0] = 22728
managers[1] = 0
managers[0] = 22728
managers[1] = 0
managers[0] = 22728
managers[1] = 0
managers[0] = 22728
managers[1] = 22737

我不明白我的代码的行为,但我猜是我错误地使用了等待函数。我使用 wait() 的方式与将 pthread_join() 用于多个 pthread 的方式相同,但这是错误的方法吗?如何让管理器进程等待它的子工作进程,让主管进程等待管理器进程?

First= 由于缺少声誉,我无法创建评论,因此我写在这里。

第二个= 去看看CodeVault的视频,简直太棒了

这是关于这个主题的第一个= https://www.youtube.com/watch?v=94URLRsjqMQ&t=561s

这是第二个= https://www.youtube.com/watch?v=VzCawLzITh0

看完之后,应该不会太难了。

您使用fork()的方式是错误的。当 fork() 被调用时,内核内部的进程将被拆分,一个新的 child 的 PID 将被创建, parent 将接收 [=43= 的 PID ], child 将收到 0

这里是如何正确使用 fork 的例子:

if ((pid = fork()) == 0) {
    //I am a child process
} else {
   // I am the parent
} 

所以在你的情况下,如果你是child(并开始执行child代码),你需要退出循环,如果你是parent,您需要存储 PID 并继续循环。

默认情况下,只有parent可以等待child和wait()waitpid()。如果 parent 对于 child 没有 wait(),则 child 将变成 zombie。现代内核会将这样的 children 分配给 PID 1(通常是 init(1)),这将清除僵尸。这被称为 reaping.

一些内核支持一个系统调用来要求你的 PID 被设置为 sub-reaper 这在这个 post 中有解释,或者在你的情况下,你可以在中间写逻辑 parents等待children.

以下是如何将所有 grandchildren 的 parent 设置为 sub-reaper 的示例:

prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);

您需要在开始创建 children 和 grandchildren 之前发出此系统调用,因此在此之后,如果中间 parent 不收集退出状态使用 wait(),child 将分配给 parent 的 PID 进行收割。

由于自动处理,测试僵尸和收获可能具有挑战性,所以我准备了一个小的 docker 容器来帮助测试收获,可以在 gitgub