僵尸进程是已终止但未被父进程回收的进程,因父进程未调用wait/waitpid导致其占用pid;可通过ps/top识别,需唤醒父进程或重启父进程清理,预防关键在于父进程正确处理sigchld并及时回收。

僵尸进程(Zombie Process)是 Linux 中一种特殊状态的进程:它已经结束运行,但其退出状态尚未被父进程读取,内核中仍保留其进程描述符。它不占用 CPU 或内存资源,但会占用一个进程 ID(PID)和少量内核数据结构空间。若大量积累,可能耗尽 PID 空间,导致无法创建新进程。
为什么会产生僵尸进程
核心原因只有一个:父进程没有及时调用 wait() 或 waitpid() 系统调用来获取子进程的退出状态。
- 子进程终止后,内核将其置为
Z(zombie)状态,并向父进程发送SIGCHLD信号 - 父进程默认忽略
SIGCHLD,若未显式处理(如注册信号处理器并调用wait),子进程就“卡”在僵尸状态 - 如果父进程先于子进程退出,子进程会被
init(PID 1)收养;正常情况下init会自动回收其子进程,不会长期滞留僵尸 - 但若父进程是守护进程、脚本或存在 bug 的程序(比如忘记
wait、死循环中漏掉回收逻辑),就容易产生僵尸
如何识别僵尸进程
使用 ps 命令查看状态列为 Z 的进程:
ps aux | grep ' Z ' —— 注意空格,避免匹配到其他含 Z 的字段
ps auxf —— 查看进程树,可直观看到僵尸进程挂在哪个父进程下
top 命令中,S 列显示 Z 即为僵尸进程
如何清理已存在的僵尸进程
僵尸进程本身不可 kill(因为它已终止),只能让其父进程主动回收:
-
向父进程发送 SIGCHLD:有时父进程设置了信号处理器但未触发,可用
kill -s SIGCHLD <ppid></ppid>尝试唤醒回收逻辑 - 重启父进程:最直接有效的方式。父进程退出后,僵尸子进程会被 init 收养并立即清理
-
不能 kill 僵尸进程本身:对 PID 执行
kill -9无效,系统会返回 “No such process”
如何预防僵尸进程产生
关键在于父进程正确处理子进程退出:
- 在 C/C++ 程序中,fork 后务必 wait/waitpid,或使用
signal(SIGCHLD, handler)并在 handler 中循环waitpid(-1, &status, WNOHANG) - 在 Shell 脚本中,避免后台子进程(
&)失控;如需异步执行,可用wait等待全部完成,或结合trap 'wait' EXIT确保退出前回收 - 使用双 fork 技巧创建守护进程时,第一个子进程退出前要确保第二个子进程已被 init 收养,避免短暂僵尸
- 监控手段:定期检查
ps aux | awk '$8 ~ /Z/ {print}',集成进运维告警流程










