首页 > 解决方案 > 在双叉中,为什么孙子退出之前不能退出?

问题描述

双叉

在我的理解中,当一个进程想要分叉一个后台进程时使用双叉,但是 1. 它不想等待它,并且 2. 后台进程应该在它退出后获得。

因此,双叉只需要父进程等待子进程,子进程在分叉孙子进程后立即退出,孙子进程作为后台进程负责真正的任务。

语境

根据 APUE 的这段摘录,孙子会休眠 2 秒以确保其父(子)在退出之前退出,这样它就会成为孤儿,而 init 会照顾它并在它退出时收割它。

#include "apue.h"
#include <sys/wait.h>

int
main(void)
{
    pid_t   pid;

    if ((pid = fork()) < 0) {
        err_sys("fork error");
    } else if (pid == 0) {      /* first child */
        if ((pid = fork()) < 0)
            err_sys("fork error");
        else if (pid > 0)
            exit(0);    /* parent from second fork == first child */

        /*
         * We're the second child; our parent becomes init as soon
         * as our real parent calls exit() in the statement above.
         * Here's where we'd continue executing, knowing that when
         * we're done, init will reap our status.
         */
        sleep(2);
        printf("second child, parent pid = %ld\n", (long)getppid());
        exit(0);
    }

    if (waitpid(pid, NULL, 0) != pid)   /* wait for first child */
        err_sys("waitpid error");

    /*
     * We're the parent (the original process); we continue executing,
     * knowing that we're not the parent of the second child.
     */
    exit(0);
}

问题

为什么孙子进程需要休眠那 2 秒?假设它在子进程退出之前就退出了,按照这个问题,当子进程退出时它仍然会被收割,而父进程仍然不需要照顾它。

这不是实现了使用双叉的最初目标吗?

标签: unixfork

解决方案


该示例的目的是演示孙子的父级在其原始父级退出后成为进程 1 (init)。

为了证明孙子的父进程成为进程 1,孙子调用getppid并打印结果。

  1. 如果孙子在其原始父级退出getppid 之前调用,则getppid返回不是 pid 1 的内容。
  2. 如果孙子在其原始父级退出getppid getppid调用,则返回 1。

示例程序的目的是使#2 发生。所以它需要确保在孙子调用之前原始父级已经退出getppid。它通过调用sleep(2)孙子来做到这一点。

在一个真正的程序中,孙子不会sleep(2)在那里。它只会做它的工作。

由于这是一个玩具程序,孙子没有真正的工作要做。


推荐阅读