孤儿进程与僵尸进程

早就了解孤儿进程与僵尸进程,但仅仅是停留在一知半解的程度,总结一下。

概念

  首先我们知道在Linux中,进程都是由父进程创建的,一般情况下子进程退出后需要父进程来清理子进程退出后留下的“垃圾”,父进程是调用wait()或waitpid()系统调用获得的子进程的终止状态。
孤儿进程:父进程在它的子进程结束之前就退出了,那么这些子进程就成为孤儿进程。孤儿进程会被init(pid=1)进程所收养,回收这些孤儿进程。
僵尸进程:父进程创建了子进程,若子进程退出,但是父进程并没有调用wait()或者waitpid()获取子进程的状态,那么子进程的进程描述符就仍然保存在系统中。这些进程称为僵尸进程。

危害

若一个进程产生子进程后不调用wait()或waitpid()的话,那么子进程退出后的进程描述符不会释放,进程号也就一直被占用,但是系统使用的进程号是有限的,如果大量产生僵尸进程,就有可能导致系统没有可用的进程号了而不能产生新进程,这就是僵尸进程的危害
孤儿进程没有父进程来回收,重任就交给了init进程上,在孤儿进程结束后init会作为父进程进行回收,所以孤儿进程一般没有什么危害

僵尸进程的解决办法

子进程在exit()退出之后,内核会释放掉进程的相关资源,留下进程描述符等一些信息等待父进程回收,这个状态称为僵尸进程,这时用ps命令就能看到子进程的转态是“Z”。退出的同时也会给父进程发送一个SIGCHILD信号
解决办法一:
父进程主动接收并处理SIGCHILD信号,在信号处理函数中调用wait()函数进程处理。

int main()
{
    ...
    Signal(SIGCHLD, sig_chld);
    ...
}
void sig_chld(int signo)
{
    pid_t        pid;
    int        stat;

    while ( (pid = waitpid(-1, &stat, WNOHANG)) >0)
        printf("child %d terminated/n", pid);
}

解决办法二:
fork两次,父进程(成为进程a)创建子进程(进程b),然后子进程再创建子进程(进程c),同时进程b退出且父进程回收,这时进程c变成孤儿进程,从而其父进程变成init进程,通过init进程就能处理僵尸进程。

你可能感兴趣的:(linux,linux内核)