温馨提示×

ubuntu 僵尸进程如何产生

小樊
45
2026-08-11 22:28:54
栏目: 智能运维

在 Ubuntu(以及所有 Linux 系统)中,**僵尸进程(Zombie Process)**的产生原因本质上和 Linux 的进程回收机制有关。下面用通俗 + 技术细节两种方式说明。


一、什么是僵尸进程

僵尸进程是一个已经结束运行,但还没有被父进程回收的进程

  • 进程已经调用了 exit()
  • 进程表中仍然保留一条记录
  • 不占用 CPU、内存等资源
  • 无法被 kill 掉

状态通常显示为:

Z

Zombie

二、僵尸进程是如何产生的

核心原因一句话总结:

子进程退出后,父进程没有调用 wait() / waitpid() 回收子进程的状态


详细过程(重点)

  1. 父进程创建子进程

    pid = fork();
    
  2. 子进程执行任务后退出

    exit(0);
    
  3. 子进程变成僵尸

    • 子进程已经死亡
    • 但内核仍保留其进程表项(PID、退出状态等)
    • 等待父进程读取退出状态
  4. 父进程没有回收

    • 父进程:
      • 忘记调用 wait()
      • 或忙于其他事情
      • 或逻辑错误
    • 子进程就一直是僵尸

三、常见产生僵尸进程的场景

1️⃣ 父进程不处理 SIGCHLD

int main() {
    if (fork() == 0) {
        exit(0);  // 子进程退出
    }
    while (1);    // 父进程什么都不做
}

✅ 子进程会立刻变成僵尸


2️⃣ 父进程是长期运行的服务(守护进程)

  • Nginx / Java / Python 服务
  • 父进程不断 fork()
  • 没有正确回收子进程

3️⃣ 父进程忽略子进程退出

signal(SIGCHLD, SIG_IGN);  // 错误用法(某些情况下)

在某些老内核或实现中,可能导致僵尸


4️⃣ 父进程先于子进程退出(但被 init 接管)

  • 父进程退出
  • 子进程被 init(PID 1)接管
  • 如果 init 没有回收(极少见),也可能僵尸

四、如何查看僵尸进程

ps aux | grep Z

或:

top

看到:

Z

或:

ps -eo pid,ppid,stat,cmd | grep Z

五、僵尸进程的危害

占用很少资源
占用 PID

如果僵尸太多:

  • PID 被耗尽
  • 无法创建新进程
  • 系统异常

六、如何清理僵尸进程(重点)

❌ 不能直接 kill

kill -9 僵尸PID   # 无效

✅ 正确做法:处理父进程

方法 1:让父进程回收

  • 在父进程中调用:
    wait(NULL);
    
    waitpid(pid, &status, 0);
    

方法 2:重启 / 杀死父进程

kill -9 父进程PID
  • 父进程死后
  • 子进程由 init(或 systemd)接管
  • init 会自动回收僵尸

这是最常见、最有效的办法


七、如何避免僵尸进程(开发建议)

✅ 正确写法

signal(SIGCHLD, SIG_IGN);  // 现代 Linux 下可避免僵尸

或:

while (waitpid(-1, NULL, WNOHANG) > 0);

✅ 使用 double fork(守护进程常用)

if (fork() == 0) {
    if (fork() == 0) {
        // 真正干活
        exit(0);
    }
    exit(0);
}
wait(NULL);

八、总结一句话

僵尸进程的产生是因为:子进程死了,父进程没管。

如果你愿意,我也可以:

  • Python / C / Shell 给你演示一个僵尸进程
  • 结合你当前遇到的实际问题分析(比如 Java / Docker / Ubuntu Server)

0