简体   繁体   English

如果父进程退出,我如何防止子进程不成为僵尸

[英]How can i prevent a child process to NOT become a zombie if parent exits

My main process spawns a child process. 我的主要过程产生了一个子进程。 If the main process is killed, the child would be assigned ppid of 1. When the child exits, it would become a zombie as init has not called wait() on this child. 如果主要进程被杀死,则子进程将被赋予ppid 1.当子进入时,它将变为僵尸,因为init没有对此子进行wait()调用。 Is there a way to avoid this situation? 有没有办法避免这种情况?

init will call wait() on processes that it inherits. init 在它继承的进程上调用wait() Zombies should only exist where the child has exited but the parent is still around, but is yet to reap the exit code. 僵尸应该只存在于孩子已经离开的地方但是父母还在,但还没有获得退出代码。 From the init manpage: init页:

init is the parent of all processes on the system, it is executed by the kernel and is responsible for starting all other processes; init是系统上所有进程的父进程,它由内核执行,负责启动所有其他进程; it is the parent of all processes whose natural parents have died and it is responsible for reaping those when they die. 它是所有过程的父母,其天然父母已经死亡, 并且有责任在他们死亡时收获这些过程。

You should make a distinction between orphans (they're still alive, their parent is dead and hence they've been adopted by init ), and zombies (they're dead but their parent is alive and has not yet reaped them). 你应该让孤儿之间的区别(但他们仍然活着,他们的父母已经死了,因此他们已经通过init )和僵尸(他们死了,但他们的父母还活着,还没有收获它们)。

Orphans will become zombies for a very short period of time after they exit but before init reaps them but this period should be small enough that no-one notices. 孤儿在退出后会在很短的时间内成为僵尸,但在init收获之前,但是这个时期应该足够小,没有人注意到。 In fact, all exiting processes (except possibly init itself) go through this short zombie phase, it's only those cases where the parent doesn't reap quickly enough that you notice. 事实上, 所有现有的进程(除了可能是init本身)都经历了这个短暂的僵尸阶段,只有那些父母没有足够快收获你注意到的情况。


The actual code in the init child death ( SIGCHLD ) handler goes something like this (my comments): init child death( SIGCHLD )处理程序中的实际代码是这样的(我的评论):

void chld_handler (int sig) {
    CHILD  *ch;
    int    pid, st;
    int    saved_errno = errno;

    while ((pid = waitpid(-1, &st, WNOHANG)) != 0) { // << WAIT done here
        if (errno == ECHILD) break;
        for (ch = family; ch; ch = ch->next) {
            if (ch->pid == pid && (ch->flags & RUNNING)) {
                INITDBG (L_VB, child_handler: marked %d as zombie", ch->pid);
                ADDSET (got_signals, SIGCHLD);
                ch->exstat = st;
                ch->flags |= ZOMBIE;                 // Set to zombie here.
                if (ch->new) {
                    ch->new->exstat = st;
                    ch->new->flags |= ZOMBIE;
                }
                break;
            }
        }
        if (ch == NULL) {
            INITDBG (L_VB, "chld_handler: unknown child %d exited.", pid);
        }
    }
    errno = saved_errno;
}

And then, later on in the main loop (not signal handler), any processes in the process table marked as ZOMBIE are cleaned up: 然后,稍后在主循环(不是信号处理程序)中,清除标记为ZOMBIE的进程表中的任何进程:

if (ISMEMBER (got_signals, SIGCHLD)) {
    INITDBG(L_VB, "got SIGCHLD");
    /* First set flag to 0 */
    DELSET(got_signals, SIGCHLD);

    /* See which child this was */
    for (ch = family; ch; ch = ch->next) {
        if (ch->flags & ZOMBIE) {                    // ZOMBIE detected here
            INITDBG (L_VB, "Child died, PID= %d", ch->pid);
            ch->flags &= ~(RUNNING|ZOMBIE|WAITING);  // And cleared here.
            if (ch->process[0] != '+') {
                write_utmp_wtmp ("", ch->id, ch->pid, DEAD_PROCESS, NULL);
            }
        }
    }
}

在程序的最后放置一个等待(NULL)语句,以便父和子等待彼此,直到它们都完成执行并且从任何人都不成为僵尸进程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM