在 Ubuntu(以及所有类 Unix 系统)里,**僵尸进程(Zombie Process)**的本质是:
子进程已经结束,但父进程还没有“收尸”(没有调用
wait()/waitpid()获取子进程退出状态)
下面从「怎么来的」「为什么还在」「常见场景」三个角度说明。
简化流程:
fork() 创建一个子进程wait() / waitpid() 来“回收”子进程在进程状态中表现为:
ps aux
状态为 Z(zombie)
僵尸进程已经死了,它:
kill -9 杀死只能:
init / systemd 接管并回收pid_t pid = fork();
if (pid == 0) {
exit(0); // 子进程退出
}
// 父进程忘了 wait()
→ 子进程变僵尸
✅ 正确做法:
wait(NULL);
或使用 signal(SIGCHLD, SIG_IGN)
父进程:
导致永远没机会 wait()
如:
apachefork例如:
sh -c 'sleep 100 &'
父 shell 退出后,子进程被 init 接管(一般没问题)
但如果父进程长期存在,就可能产生僵尸
ps aux | grep Z
或:
top
看 Tasks: x total, y zombie
pstree -p | grep Z
kill -9 父进程PID
之后由 systemd(PID 1)回收
wait()sigaction(SIGCHLD)kill -9 僵尸PID
没用,僵尸已经死了
少量僵尸:
大量僵尸:
如果你愿意,可以:
ps / pstree 输出我可以帮你具体分析是哪种原因。