僵尸进程和孤儿进程

首先简单认识下僵尸进程和孤儿进程:
僵尸进程
一个进程使用fork()创建子进程,在子进程死亡时,其父进程没有调用wait函数或者waitpid()函数获取子进程的状态信息,那么子进程的描述符会仍然保存在系统中,这种进程被称为僵尸进程。
孤儿进程
如果父进程退出,而它的一个或多个子进程仍然在运行,那么这些进程则会被称为孤儿进程,会被init(1号)进程所领养,并负责回收它们的状态信息。

孤儿进程是无害的,但僵尸进程有害
僵尸进程为什么有害
unix里有一种机制就是父进程需要知道子进程的退出信息,当一个进程结束时,内核会释放掉这个进程的所有资源(打开的文件,占用的内存)。但是还需要保留一部分退出信息(进程号,退出状态,运行时间等等),直到父进程wait或waitpid后才会被释放。那么可以推出如果父进程没有调用wait或waitpid去回收子进程的退出信息,那么子进程的进程号等退出信息会一直都在系统中。这些进程号会被占用,但系统使用的进程号是有限的,这样持续下去系统就无法产生新的子进程。

避免僵尸进程
最容易想到的就是调用wait函数去回收子进程,创建多少回收多少。
也可以使用两次fork的方法去避免僵尸进程的产生。(其原理是利用当起父进程死亡时,该进程会成为孤儿进程被号进程所收养,1号进程会自动回收其孤儿进程的退出信息).

//代码参照UNIX高级环境编程
#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)  // 第一个子进程  
    {  
        if ((pid = fork()) < 0)  
            err_sys("fork error");  
        else if (pid > 0)  
            exit(0);    //第二个子进程的父进程终止(第一个子进程)  

        //这里是第二个子进程(孤儿进程),其父进程已经变成了init进程,当亲生父进程在上面调用exit()终止后,在此处继续执行,当第二个子进程终止的时候,父进程init会获取其状态,从而避免僵尸进程嗯。  

        sleep(2);    //保证父进程优先运行(第一个子进程)  
        printf("second child, parent pid = %d/n", getppid()); //获取父进程ID(即init ID,为1)  
        exit(0);    //第二个子进程终止  
    }  

    if (waitpid(pid, NULL, 0) != pid) //等待第一个子进程  
        err_sys("waitpid error");  

    printf("i am the parents of your parents/n");  

       //这里是继续执行原始父进程(第一个父进程),且知道不是第二个子进程的父进程  

    exit(0); //第一个父

猜你喜欢

转载自blog.csdn.net/nuyexiaoxiang/article/details/79528462