在 Debian(以及其它 Linux 发行版)里,“僵尸进程(zombie)”本质上是已经结束但父进程还没调用 wait() 回收的子进程。僵尸进程不占 CPU、不占内存,但会占用 PID 表项,过多时可能导致无法创建新进程。
预防僵尸进程的核心思路是:让父进程正确回收子进程,或让 init 接管孤儿进程。
下面从原理到实践说明。
wait() / waitpid()在 C / 程序中:
signal(SIGCHLD, SIG_IGN);
或:
while (waitpid(-1, NULL, WNOHANG) > 0);
✔ 推荐使用 SIGCHLD + waitpid(WNOHANG)
适用于写服务程序:
pid = fork();
if (pid == 0) {
fork(); // 孙子进程
exit(0);
}
wait(NULL);
孙子进程退出后由 init (PID 1) 回收,不会变僵尸。
signal(SIGCHLD, SIG_IGN);
✅ 内核自动回收子进程
⚠ 不适用于需要获取子进程退出状态的场景
Type= 可避免僵尸示例:
[Service]
Type=simple
ExecStart=/usr/bin/myserver
❌ 错误示例:
./child &
✅ 正确:
./child &
wait
查看僵尸:
ps aux | awk '$8 ~ /Z/'
查看数量:
ps -e | grep defunct | wc -l
若父进程是 bug 程序:
kill -TERM 父PID
→ 子进程变孤儿,被 systemd/init 回收
kill -9 僵尸(无效)✅ 预防僵尸进程的关键:
SIGCHLD + waitpid如果你愿意,可以:
我可以给你针对性写法。