在 Ubuntu(或者说 Linux 通用)里,**僵尸进程(zombie)**本质上是“已经结束但父进程还没回收的进程”。避免僵尸进程,核心思路是:让父进程正确回收子进程,或把子进程交给 init 接管。
下面按「原理 → 常见做法 → 示例」说明。
exit() 结束wait() / waitpid()Z(zombie)状态,等待父进程回收僵尸进程不占 CPU/内存,只保留 PID 和退出状态,但多了会耗尽 PID。
父进程捕获 SIGCHLD,在信号处理函数中 waitpid()。
#include <signal.h>
#include <sys/wait.h>
void sigchld_handler(int sig) {
while (waitpid(-1, NULL, WNOHANG) > 0);
}
signal(SIGCHLD, sigchld_handler);
✅ 推荐做法(最标准)
适合简单程序:
pid_t pid = fork();
if (pid == 0) {
exit(0);
} else {
wait(NULL);
}
⚠️ 注意:wait() 会阻塞父进程
signal(SIGCHLD, SIG_IGN);
父进程 fork → 子进程再 fork → 孙进程被 init 接管
pid_t pid = fork();
if (pid == 0) {
fork(); // 孙进程
exit(0);
}
wait(NULL);
✅ 孙进程退出后由 init(PID 1)回收
systemd 管理服务setsid() 脱离终端systemctl start myapp
systemd 会自动回收子进程
./app & disown
nohup ./app &
ps aux | grep ' Z'
或:
top
# 看 Tasks: x zombie
ps -o ppid= -p <zombie_pid>
kill -9 父进程(谨慎)✅ 写程序时:
waitpid() + SIGCHLDfork 两次✅ 运维时:
如果你愿意,我可以: