温馨提示×

ubuntu僵尸进程怎么产生

小樊
40
2026-09-04 02:34:23
栏目: 智能运维

在 Ubuntu(以及所有类 Unix 系统)中,**僵尸进程(Zombie Process)**的产生原因本质上只有一个:子进程已经结束,但父进程没有回收它的退出状态

下面从原理、常见产生方式、示例和说明几个角度讲清楚。


一、僵尸进程产生的根本原理

  1. 进程结束时会做两件事

    • 释放大部分资源(内存、文件等)
    • 保留一个最小的 task_struct,里面存着退出码、退出状态
  2. 父进程需要调用

    • wait()
    • waitpid()

    来“收尸”(读取子进程退出状态)

  3. 如果父进程不调用 wait

    • 子进程就变成 Z 状态(zombie)
    • ps 中显示 Zdefunct

僵尸进程已经“死”了,只是还留在进程表里


二、Ubuntu 中僵尸进程常见产生方式

1️⃣ 父进程什么都不做(最常见)

#include <unistd.h>

int main() {
    if (fork() == 0) {
        // 子进程
        _exit(0);
    }
    // 父进程不 wait,直接 sleep
    sleep(100);
}

运行后:

ps aux | grep defunct

会看到子进程是 Z


2️⃣ 父进程逻辑错误,忘记 wait

pid_t pid = fork();
if (pid == 0) {
    // child
    exit(0);
}
// 父进程忘记 wait
while (1) {
    // do something
}

3️⃣ 信号屏蔽或异步逻辑问题

  • 父进程用 signal(SIGCHLD, SIG_IGN) 但没正确处理
  • 父进程在 wait() 前被阻塞
  • 多线程程序中只在主线程 wait

4️⃣ 父进程自己也卡死 / 阻塞

  • 父进程死循环
  • 父进程在 I/O 上阻塞
  • 父进程被 SIGSTOP

→ 子进程退出后无人回收


5️⃣ 守护进程 / 服务bug

一些 Ubuntu 服务(如某些老版本 init 脚本、自定义 daemon)
如果:

  • fork 子进程
  • 不 wait
  • 不忽略 SIGCHLD

就会不断产生僵尸


三、僵尸进程的特征

ps -l

状态为:

Z

或:

<defunct>

示例:

 PID  PPID STAT COMMAND
1234  1000 Z    ./a.out <defunct>

四、僵尸进程的危害

不占 CPU不占内存

❌ 但:

  • 占用 进程号(PID)
  • 进程表满 → 无法创建新进程
  • 系统异常(极端情况)

五、如何解决 / 避免

✅ 正确方式(推荐)

wait(NULL);
// 或
waitpid(pid, NULL, 0);

或用 SIGCHLD

signal(SIGCHLD, SIG_IGN); // 内核自动回收

✅ 父进程死了怎么办?

如果父进程退出:

  • 僵尸进程会被 init(PID 1)接管
  • Ubuntu 中通常是 systemd
  • init 会自动 wait(),僵尸消失

❌ 不能 kill 僵尸进程

kill -9 <zombie_pid>  # 无效

因为:

僵尸已经死了,只能“回收”,不能“杀”


六、一句话总结

Ubuntu 僵尸进程的产生原因只有一个:子进程退出了,父进程没调用 wait() 回收它。

如果你愿意,我可以:

  • 给你 真实 C / Python 示例
  • 帮你 分析某个 ps 输出
  • systemd 下为什么很少看到僵尸

直接贴现象就行。

0