在 Ubuntu(以及所有类 Unix 系统)中,**僵尸进程(Zombie Process)**的产生原因本质上只有一个:子进程已经结束,但父进程没有回收它的退出状态。
下面从原理、常见产生方式、示例和说明几个角度讲清楚。
进程结束时会做两件事
task_struct,里面存着退出码、退出状态父进程需要调用
wait()waitpid()来“收尸”(读取子进程退出状态)
如果父进程不调用 wait
ps 中显示 Z 或 defunct僵尸进程已经“死”了,只是还留在进程表里
#include <unistd.h>
int main() {
if (fork() == 0) {
// 子进程
_exit(0);
}
// 父进程不 wait,直接 sleep
sleep(100);
}
运行后:
ps aux | grep defunct
会看到子进程是 Z
pid_t pid = fork();
if (pid == 0) {
// child
exit(0);
}
// 父进程忘记 wait
while (1) {
// do something
}
signal(SIGCHLD, SIG_IGN) 但没正确处理wait() 前被阻塞SIGSTOP→ 子进程退出后无人回收
一些 Ubuntu 服务(如某些老版本 init 脚本、自定义 daemon)
如果:
就会不断产生僵尸
ps -l
状态为:
Z
或:
<defunct>
示例:
PID PPID STAT COMMAND
1234 1000 Z ./a.out <defunct>
✅ 不占 CPU ✅ 不占内存
❌ 但:
wait(NULL);
// 或
waitpid(pid, NULL, 0);
或用 SIGCHLD:
signal(SIGCHLD, SIG_IGN); // 内核自动回收
如果父进程退出:
systemdwait(),僵尸消失kill -9 <zombie_pid> # 无效
因为:
僵尸已经死了,只能“回收”,不能“杀”
Ubuntu 僵尸进程的产生原因只有一个:子进程退出了,父进程没调用 wait() 回收它。
如果你愿意,我可以:
直接贴现象就行。