【Linux】为什么有僵尸状态,什么是僵尸进程,造成危害以及如何避免“内存泄漏”问题详解

在这里插入图片描述

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶🔹C++🔹Liunx
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍

一、什么是僵尸状态?

⭐️用一个生动形象的比喻来描述僵尸状态:

  • 学校星期五最后一节课大扫除,我们每次打扫完成后,不会立即就回家🏡,而是必须等待老师👱来验收完成后我才能回家。
  • 进程完成后,不能立即退出(回家🏡),必须等待父进程(老师👱)来获取子进程的信息后才能彻底释放掉。那这个等待的过程与僵尸状态十分相似。

二、为什么要有僵尸状态?

学习这里需要一些前提知识~~进程退出码

简单来说就是一个子进程进程既然被创建出来,那么一定是带着任务来的,你的任务完成情况需要有人来读取,否则,你做的是无用功啊。就好比老板让你干事,你干完就溜了,也不汇报一下完成情况怎么样,老板也不知道你到底是干了没有。

三、写个代码,感受一下

这个代码主要意思就是。子进程和父进程一起执行三秒,三秒之后呢,子进程正常退出,父进程继续执行。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 
  5 int main(void)
  6 {
  7     pid_t id = fork();
  8     if(id == 0)
  9     {
 10         // child
 11         int cnt = 3;
 12         while(cnt)
 13         {
 14             printf("I am child, pid: %d, ppid: %d, cnt: %d\n", getpid(), getppid(), cnt);
 15             sleep(1);
 16 
 17             cnt--;
 18         }                                                                                                    
 19         exit(0);
 20     }
 21     else
 22     {
 23         // father   
 24         while(1)
 25         {
 26             printf("I am father, pid: %d, ppid: %d\n", getpid(), getppid());
 27             sleep(1);
 28         }
 29     }
 30     return 0;
 31 }

就会得到如下信息:
在这里插入图片描述
❗️注意:如果子进程退出,而父进程并没有调用waitwaitpid获取子进程的状态信息(通俗讲就是回收子进程),那么子进程的进程描述符仍然保存在系统中。

  • 这也是上面程序执行后,我们为什么能看到Z状态的原因。

!wait 阻塞函数作用

1️⃣ .阻塞并等待子进程退出
2️⃣ .回收子进程残留资源
3️⃣ .获取子进程结束状态(退出原因)
4️⃣.调用一次只能回收一个子进程

四、子进程需要回收退出信息,那父进程呢?

千万不要误解以为使用fork()函数创建一个子进程,那么父进程就没人管了,所有进程都有一个顶级的父亲bash,也就是经常看到的一个进程PID为27414的这么一个进程。所以,就算是父进程它退出时依然会先进入僵尸状态–被bash读取相关退出信息后再释放它的资源–进入死亡状态

五、 为什么平常见不到Z状态呢?

所有的进程退出时,一定是先经历Z(僵尸状态),才会到X(死亡状态)。但是由于操作系统的速度十分,进程一退出就立马有父进程来回收子进程信息了,就像前面学习运行状态时,我们总是能看到睡眠状态,而运行状态会一闪而过或是直接不显示了

六、僵尸进程有什么危害呢?【内存泄露】

进程一般退出的时候,一般其不会立即彻底退出,它的代码和相关数据已经释放,但是,它的task_struct对象依然还在内存中,仍然占用内存!!。如果父进程没有主动回收子进程信息,子进程会一直让自己处于Z状态,这也是为了方便后续父进程读取子进程的相关退出结果。

那如果一个父进程一直不去不去回收已经退出的子进程的信息,就会造成 内存泄露

在这里插入图片描述

七、如何预防僵尸进程不被父进程回收

1️⃣ 让父进程调用 wait 或 waitpid 函数来回收子进程的资源,并获取其退出状态。
2️⃣ 让父进程忽略 SIGCHLD信号,这样子进程结束后会被自动回收,不会变成僵尸进程。
3️⃣杀死父进程,让子进程成为孤儿进程,由 init 进程接管并回收。

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿然成长日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值