Linux 进程状态 — 僵尸进程



🎁个人主页: 工藤新一¹

🔍系列专栏: C++面向对象(类和对象篇)

🌟心中的天空之城,终会照亮我前方的路

🎉欢迎大家点赞👍评论📝收藏⭐文章


文章目录

  • [进程状态 --- 僵尸进程](#进程状态 — 僵尸进程)
    • [一、进程状态 --- Zombies](#一、进程状态 — Zombies)
    • 二、僵尸进程
      • [2.1 什么是僵尸进程?](#2.1 什么是僵尸进程?)
      • [2.2 为什么会有僵尸进程?](#2.2 为什么会有僵尸进程?)
      • [2.3 僵尸进程的危害?](#2.3 僵尸进程的危害?)
      • [2.4 如何产生一个僵尸进程?](#2.4 如何产生一个僵尸进程?)
      • [2.5 如何清除僵尸进程?](#2.5 如何清除僵尸进程?)
      • [2.6 如何避免僵尸进程?](#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代码示例:

cpp 复制代码
#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()

🌟 各位看官好我是工藤新一¹呀~

🌈 愿各位心中所想,终有所致!

相关推荐
groundhappy1 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕2 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫3 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生3 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.115 小时前
linux基础IO
linux·运维·服务器
BelongPanda7 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯7 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_777998347 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器
yunwei377 小时前
eBPF 教程:检查 exec 后真正安装的可执行镜像
linux·开源
笑锝没心没肺8 小时前
yum update 报错:GPG key retrieval failed: [Errno 14] HTTPS Error 404 - Not Found
linux·运维·服务器