【Linux】浅聊僵尸态进程的产生原因与危害

这篇博客中,我们将简单聊一聊——僵尸态进程的产生原因与危害,但在了解这些之前,我们还需要了解一些东西,例如进程的基本构成以及什么是僵尸态进程等概念

进程的基本构成

在32位机中,系统为一个进程分配的大小为4G(1K = 1024 = 2^10;1M =  2^20;1G = 2^30;所以4G = 2^32),其中0-3G为用户空间,3-4G为内核空间,用户空间与内核空间里的数据我们就在这里不赘述了,具体构成大家可以看看下图

【Linux】浅聊僵尸态进程的产生原因与危害_第1张图片

僵尸态进程产生的原因

要想了解僵尸态进程为何产生,我们要先来了解而以下几点:

1.什么是僵尸态

当子进程退出时,父进程没有读取到子进程的返回代码,子进程就会进入僵尸态。僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取返回代码。

2.僵尸态进程的产生过程

在了解了什么是僵尸态后,我们来聊一聊什么是僵尸态进程是怎么产生的

为什么这种进程会被称为僵尸态进程呢?重点就和这“僵尸”二字有关。说是僵尸,其实更像是丧尸。丧尸其实就是失去了人性,残留在人世间的嗜血尸体。

僵尸态进程的产生过程

  1. 子进程先于父进程退出,子进程的用户空间被系统释放
  2. 但是这时,父进程没有读到子进程的返回代码,不知道子进程退出了
  3. 因为父进程没有读到子进程的返回代码,所以系统故意残留了子进程内核空间里的部分PCB,导致子进程没有被回收完全,从而产生了僵尸态进程。具体情况如下图所示

【Linux】浅聊僵尸态进程的产生原因与危害_第2张图片

接下来,我们来做几个简单的操作,验证我们上述的讲解是否正确,同时也来帮大家加深印象

我们来创建一个main.c的文件,具体代码以及操作步骤如下所示

#include
#include//getpid()函数的头文件

int main()
{
    pid_t pid;
    pid = fork();
    //父进程进入该判断并被阻塞
    if(pid > 0)
    {
        //让父进程一次睡两秒
        while(1)
        {
            printf("Father Process %d is sleeping now \n",getpid());
            sleep(2);
        }
    }
    else if(pid == 0)
    {
        int count = 8;
        while(1)
        {
            //当count<0时,子进程退出循环
            //此时父进程仍在循环,无法得到子进程的返回代码,僵尸态进程产生
            if(count <= 0)
            {
                break;
            }
            printf("Child Process %d count = %d\n",getpid(),count);
            count--;
            sleep(1);
        }
        printf("Zombie Process %d Generate!\n",getpid());
    }
    //如果子进程创建失败
    else if(pid < 0)
    {
        perror("Child Process fork Failed!\n");
        return 0;
    }
    return 0;
}

【Linux】浅聊僵尸态进程的产生原因与危害_第3张图片

可以发现,打印结果与我们所期望的一样,子进程每一次睡一秒,父进程每次睡两秒,8秒后,子进程退出,父进程仍在循环,没有得到子进程的返回代码,自此子进程变成了僵尸进程,也就是那一句“Zombie Process 7777 Generate!”。

我们再来检验一下,子进程是否成为了僵尸进程,结果如下图所示

【Linux】浅聊僵尸态进程的产生原因与危害_第4张图片

僵尸的英文为Zombie,所以这里子进程的状态就是Z+,也就是僵尸态。自此,僵尸态进程的产生过程就大体讲解完毕了,相信大家也就明白了僵尸态进程产生的原因了

总而言之,就是只要子进程退出,父进程还在运行,但父进程没有读取到子进程的返回代码,子进程就会进入僵尸态

但接下来我们要关注一个细节——在第3步中,为什么父进程没有读到子进程的返回代码后,系统就会故意留下子进程内核空间里的部分PCB呢?这里就涉及到一个小细节了

【Linux】浅聊僵尸态进程的产生原因与危害_第5张图片

小细节——为什么系统会残留部分PCB

要想解释此情况的产生原因,举个形象的小例子再合适不够了

我们来做一个情景假设——

有一个人叫张三,他爹叫李四,有一天张三突然死掉了,原因未知,尸体刚送到医院,还没等李四到呢,结果医院一把火给尸体烧了,李四纳了闷了——“不是哥们,我儿子你杀的呀,连看都不让我看一下吗?我连我儿子咋死的都不知道啊?”。

诶,这句话就是问题的关键,这个子进程是我父进程创建的啊,我这个子进程咋死的我总得知道啊。正巧的是,子进程的退出原因就放在其PCB里面,所以当父进程没有读到子进程的返回代码时,系统就会留下该子进程的部分PCB,以供其父进程来读取子进程的退出原因并回收该PCB,回收完成后,子进程也会退出僵尸态

总而言之,系统残留僵尸进程部分PCB的原因就是供父进程进行验尸,也就是查询退出原因

僵尸态进程的危害

  1. 由于PCB创建的数量是固定的,一个僵尸进程会占用一个PCB,所以影响其他进程的创建
  2. 造成了内存泄漏(内存泄漏的定义——内存空间在使用完毕后未被回收,结果导致该内存单元一直被占据,直到程序结束)

大家有什么地方没有看懂的话,可以在评论区留言给我,咱要力所能及的话就帮大家解答解答

今天的学习记录到此结束啦,咱们下篇文章见,ByeBye!

你可能感兴趣的:(Linux,linux,学习)