Linux 进程状态 — 僵尸进程
🎁个人主页:工藤新一¹
🔍系列专栏:C++面向对象(类和对象篇)
🌟心中的天空之城,终会照亮我前方的路
🎉欢迎大家点赞👍评论📝收藏⭐文章
文章目录
- 进程状态 — 僵尸进程
- 一、进程状态 — Zombies
- 二、僵尸进程
- 2.1 什么是僵尸进程?
- 2.2 为什么会有僵尸进程?
- 2.3 僵尸进程的危害?
- 2.4 如何产生一个僵尸进程?
- 2.5 如何清除僵尸进程?
- 2.6 如何避免僵尸进程?
进程状态 — 僵尸进程
一、进程状态 — Zombies
- Z (Zombies):进程已经执行完毕并终止了,但其父进程还没有调用
wait()
或waitpid()
系统调用来回收它子进程退出状态信息。此时,这个已经死亡的进程就成为了 “僵尸进程”。 - 重要:僵尸进程已经不占用任何内存或CPU资源,它仅仅在进程表中保留一个入口,记录其退出状态,供父进程查询。如果父进程一直不回收,它就会一直存在 -(僵死进程会以终⽌状态保持在进程表中,并且会⼀直在等待父进程读取退出状态代码)
- 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入 Z(Zombies) 状态
二、僵尸进程
2.1 什么是僵尸进程?
故事插入:
如上所述,僵尸进程是一个已经终止但尚未被其父进程回收的进程。
2.2 为什么会有僵尸进程?
这是Unix系统进程状态设计的一部分。设置僵尸状态是为了维护进程的退出信息,以便父进程能够查询子进程是如何死掉的(是正常退出还是被信号杀死?退出码是多少?)。
只有当父进程读取了这些信息后,内核才会彻底清除这个僵尸进程。
1.那些信息:进程退出时,必须要维持进程的基本相关信息(哪些基本信息?),让父进程得知其退出情况
2.信息存在哪里?当进程退出时,其退出信息是要保存在 task_struct
中(因为代码、数据已经被释放了,就只剩下 PCB
了),必须维持PCB(操作系统中的数据结构)。我们可以通过父进程的系统调用获取到子进程的特殊信息,我们就知道这个进程是因为什么原因而退出的。所以在子进程已经退出之后,父进程没有获取子进程的信息之前,这个子进程就是僵尸进程
2.3 僵尸进程的危害?
- 资源占用:僵尸进程本身不消耗内存和CPU。
- 主要危害:每个僵尸进程都会在系统的进程表中占用一个槽位(即一个进程ID,PID)。如果系统中存在大量僵尸进程,进程表会被填满,导致系统无法创建新的进程,从而引发严重问题。
- 内存泄漏问题
2.4 如何产生一个僵尸进程?
一个典型的例子:父进程创建了子进程,但父进程忙于自己的工作,没有调用 wait()
来等待子进程结束。子进程先于父进程结束,就会变成僵尸。
简单C代码示例:
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>int main () {pid_t child_pid = fork(); // 创建子进程if (child_pid > 0) {// 父进程sleep(60); // 父进程睡眠60秒,而不调用 wait()// 在这60秒内,子进程已经结束,会成为僵尸} else {// 子进程exit(0); // 子进程立即退出}return 0;
}
编译运行上述程序,在父进程睡眠的60秒内,用 ps aux | grep Z
命令就可以看到状态为 Z+
的子进程。
验证 “Z” 状态
处于僵尸状态的进程的PCB需一直维护,而PCB
本就是一个进程的 task_struct
的对象,这会一直占用内存空间 —— 引发内存泄漏问题!
所以,不是只有 new/malloc
会引起内存泄漏
,僵尸进程也会引起内存泄漏
—— 解决方法:通过 wait()_pid
的方式等待子进程并获取子进程退出结果
因此,父进程在未来除了获取子进程退出信息,还会进入等待模式将子进程的PCB释放掉 —— 解决内存泄漏问题
2.5 如何清除僵尸进程?
- 正确方法:让父进程调用
wait()
或waitpid()
来回收子进程。 - 常用方法:如果父进程不回收,最直接的方法就是杀死父进程。父进程被杀后,其所有子进程(包括僵尸进程)会变成“孤儿进程”,被 init 进程(PID=1)收养。init 进程会定期调用
wait()
,从而清理这些僵尸进程。- 命令:
kill <父进程的PID>
- 命令:
- 警告:不要试图用
kill -9
杀死僵尸进程本身,因为它已经是死掉的进程,信号无法作用在它身上。
2.6 如何避免僵尸进程?
- 在编写程序时,父进程应该使用
wait()
或waitpid()
系统调用来等待子进程结束。 - 或者,父进程可以捕获
SIGCHLD
信号(当子进程状态改变时,内核会向父进程发送此信号),并在信号处理函数中调用wait()
。
🌟 各位看官好,我是工藤新一¹呀~
🌈 愿各位心中所想,终有所致!