我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。 当一个 进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。孤儿进程和僵尸进程都是对不正常状态的子进程的称呼,区别如下:

孤儿进程:孩子还在,爹没了

一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
由于孤儿进程会被init进程给收养,所以孤儿进程不会对系统造成危害

僵尸进程:孩子死了,没心没肺的爹成天出去浪也不给收尸,子进程变成了僵尸...

一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。

僵死进程的危害:

unix提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息, 就可以得到。这种机制就是: 在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。 但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放。 但这样就导致了问题,如果进程不调用wait / waitpid的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。

任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。 如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。

一个进程如果只复制fork子进程而不负责对子进程进行wait()或是waitpid()调用来释放其所占有资源的话,那么就会产生很多的僵死进程,如果要消灭系统中大量的僵死进程,只需要将其父进程杀死,此时所有的僵死进程就会变成孤儿进程,从而被init所收养,这样init就会释放所有的僵死进程所占有的资源,从而结束僵死进程。

下面我们用一个小程序来演示如何制造一个孤儿进程和一个僵尸进程。正常而正确的进程如下:

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
main()
{
    pid_t pid;
    int status, i;
    )
    {
        printf("This is the child process. pid =%d\n", getpid());
        exit();
     }
    else
    {
        sleep();
        printf("This is the parent process, wait for child...\n");
        pid = wait(&status);
        i = WEXITSTATUS(status);
        printf("child's pid =%d . exit status=%d\n", pid, i);
    }
}

以上代码中父进程等待子进程退出后父进程自己再退出,查看进程列表没有任何异常。我们来修改下让父进程早于子进程退出:

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
main()
{
    pid_t pid;
    int status, i;
    )
    {
        printf("This is the child process. pid =%d\n", getpid());
        sleep();
        //exit(5);
     }
    else
    {
        sleep();
        printf("This is the parent process, wait for child...\n");
        //pid = wait(&status);
        //i = WEXITSTATUS(status);
        //printf("child's pid =%d . exit status=%d\n", pid, i);
    }
}

以上程序让子进程延迟120秒,父进程不等待子进程提前退出,那么子进程将变成孤儿,并由1号进程收养,待120秒后退出。在120秒内查看进程列表,54035是进程号,1号是它的父进程号也就是它的养父1号进程。如下所示:

让我们再来修改下代码,让子进程先退出,父进程不退出但是也不wait子进程,即不对完成执行的子进程回收资源,代码如下:

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
main()
{
    pid_t pid;
    int status, i;
    )
    {
        printf("This is the child process. pid =%d\n", getpid());
        exit();
     }
    else
    {
        sleep();
        printf("This is the parent process, wait for child...\n");
        //pid = wait(&status);
        //i = WEXITSTATUS(status);
        //printf("child's pid =%d . exit status=%d\n", pid, i
    }
}

子进程先退出,父进程不退出但是也不wait子进程,即不对完成执行的子进程回收资源。那么这个子进程将变成僵尸进程。查看进程列表如下

54981是父进程,54982是子进程,可以看出该子进程变成了僵尸进程(defunct process).当父进程结束时,该僵尸进程变成孤儿进程将由1号进程接管并回收资源。

孤儿进程VS僵尸进程的更多相关文章

  1. [Linux] 孤儿进程与僵尸进程[总结]

    转载: http://www.cnblogs.com/Anker/p/3271773.html 1.前言 之前在看<unix环境高级编程>第八章进程时候,提到孤儿进程和僵尸进程,一直对这两 ...

  2. wait函数返回值总结,孤儿进程与僵尸进程[总结]

    http://blog.csdn.net/astrotycoon/article/details/41172389 wait函数返回值总结 http://www.cnblogs.com/Anker/p ...

  3. 020_Linux的孤儿进程与僵尸进程(Unix系统编程)

    1.前言 之前在看<unix环境高级编程>第八章进程时候,提到孤儿进程和僵尸进程,一直对这两个概念比较模糊.今天被人问到什么是孤儿进程和僵尸进程,会带来什么问题,怎么解决,我只停留在概念上 ...

  4. [linux]孤儿进程与僵尸进程

    转载自:http://www.cnblogs.com/Anker/p/3271773.html 一.前言 之前在看<unix环境高级编程>第八章进程时候,提到孤儿进程和僵尸进程,一直对这两 ...

  5. Perl进程:僵尸进程和孤儿进程

    概念 僵尸进程:当子进程退出时,父进程还没有(使用wait或waitpid)接收其退出状态时,子进程就成了僵尸进程 孤儿进程:当子进程还在运行时,父进程先退出了,子进程就会成为孤儿进程被pid=1的i ...

  6. PHP7 网络编程(三)孤儿进程与僵尸进程

    基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当一个 ...

  7. 二十三、Linux 进程与信号---进程链和进程扇、守护进程和孤儿进程以及僵尸进程

    23.1 进程链和进程扇 23.1.1 概念 进程链:一个父进程构建出一个子进程,子进程再构建出子子进程,子子进程构建出子子子进程.... 这种就为进程链 进程扇:一个父进程构建出多个子进程,子进程都 ...

  8. 【Linux 进程】孤儿进程、僵尸进程和守护进程

    1.孤儿进程: 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程.孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作.孤儿进程是 ...

  9. linux下的进程(孤儿进程、僵尸进程)

    linux提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息,就可以得到.这种机制就是:在每个进程退出的时候,内核释放该进程所有的资源,包括打开文件,占用的内存等.但是仍然为其保留一定的信息 ...

随机推荐

  1. JRockit Mission Control建立到Tomcat的连接(windows)

    http://www.360doc.com/content/10/0928/16/203871_57086538.shtml  蓝海豹 JRockit Mission Control建立到Tomcat ...

  2. nodejs静态web服务

    项目准备 Web 服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以向浏览器等 Web 客户端提供文档,也可以放置网站文件,让全世界浏览:可以放置数据文件,让全世界下载.目前最主流的 ...

  3. 【转】Python 之 元类

    原文链接: https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python      http://python.jo ...

  4. spring boot profiles 实现多环境下配置切换 docker版

    1,前言 开发环境总需要调试,docker直接部署不需要调试,环境配置不一样,这里的目的只是,在docker文件环境与开发环境使用不同的配置文件,项目结构如下 2,设置项目配置文件 默认配置文件 ap ...

  5. jmeter接口测试-GET请求路径中包含特殊字符或中文导致Response400报错

    问题描述:接口测试中异常用例GET请求路径中包含特殊字符或中文,运行jmeter会报错,取样器中只能看到Response400,响应结果为空 解决思路: 对于通过BODY发送的中文内容可以用Jmete ...

  6. 升级到 .NET Core 2.1

    从 .NET Core 2.0 升级到 .NET Core 2.1 最近在翻译 <Pro ASP.NET Core MVC 2>这本书,书中的示例是以 .NET Core 2.0 为基础的 ...

  7. xshell使用密钥登陆linux

    一.环境CentOS 7.4xshell 6 二.介绍远程ssh连接服务器 默认是用的密码验证的方式,而且还是root账号,这样的验证方式会有安全隐患,容易被人暴力破解root密码.如果改成用密钥登陆 ...

  8. Monkey脚本API

    Monkey脚本API简介 LaunchActivity(pkg_name, cl_name):启动应用的Activity.参数:包名和启动的Activity. Tap(x, y, tapDurati ...

  9. CUDA编程模型——组织并行线程3 (2D grid 1D block)

    当使用一个包含一维块的二维网格时,每个线程都只关注一个数据元素并且网格的第二个维数等于ny,如下图所示: 这可以看作是含有二维块的二维网格的特殊情况,其中块儿的第二个维数是1.因此,从块儿和线程索引到 ...

  10. vue简单的导航栏

    <style> img{ display:block; margin:0 auto; width:500px; height:500px; } #app li{ list-style: n ...