僵尸进程和孤儿进程有什么区别?为什么 kill 不掉僵尸进程?
下面是一段教学用的模拟面试。
🧑💻 面试官:僵尸进程和孤儿进程有什么区别?
🙋♂️ 我:僵尸进程已经退出,但父进程还没回收;孤儿进程是父进程先退出。
🧑💻 面试官:那给僵尸进程发 kill -9,为什么没用?
🙋♂️ 我:它已经不在执行了。
🧑💻 面试官:如果它的父进程仍然活着,应该修哪里?容器里 PID 1 又需要承担什么职责?
一个是「退出结果没人领取」,一个是「原父进程离开」。先分清退出状态和父子关系,才知道应该处理谁。
面试速答(60 秒版)
僵尸进程是子进程已经退出,但父进程尚未通过 wait 等方式领取退出状态。内核还保留必要信息,因此它仍可能出现在进程列表中,但已经不运行正常代码。
孤儿进程则是原父进程先退出,而子进程仍然存在。它会被相应的收养进程接管,在 Linux 中可能是子进程收割器或所在命名空间的初始化进程。
所以僵尸不能靠再杀一次自己来解决,应该让父进程正确回收。孤儿也不等于异常进程,它可能继续正常运行。
实际排查时,我会检查进程状态、PPID 和父进程的子任务管理。容器中的 PID 1 也需要正确转发信号和回收子进程,不能只启动业务程序就忽略这些职责。

图:init 只是收养孤儿的一个示例;Linux 上也可能由最近的 subreaper 接管。
知识点详解:为什么退出后,还能在进程表里看到它?
子进程退出,父进程还需要知道结果
假设一个服务启动命令行工具处理文件。工具结束后,父进程需要知道退出码、信号等结果,才能判断任务成功还是失败。
因此,子进程退出并不意味着所有记录立刻消失。内核会保留供父进程领取的退出信息。当父进程执行 wait、waitpid 等操作后,相关僵尸记录才被回收。
僵尸通常不再保留正常运行所需的完整地址空间,也不继续消耗 CPU 执行业务。但大量未回收记录会占用进程相关资源,仍然是需要修复的问题。
具体等待与状态回收规则见 wait 手册。
为什么 kill -9 杀不掉僵尸?
kill 发送的是信号。僵尸已经完成退出,不是一个卡在循环里的工作进程,无法再靠信号让它“再退出一次”。
应该检查父进程为什么没有领取结果:是不是启动子进程后丢了句柄,异常分支没有 wait,或者只回收了一个子进程而漏掉其他。
不要直接把杀父进程当作常规修复。让父进程退出后,僵尸可能被接管并回收,但父进程可能承载重要业务。应先评估影响,再修正子任务管理。

图:子进程结束,父进程领取退出状态。
孤儿进程,不代表已经退出
如果父进程先结束,而子进程仍在处理文件,它成为孤儿。Linux 会重新安排父子关系,由最近适用的 subreaper 或初始化进程接管。
这与僵尸不同:孤儿描述父子关系,僵尸描述退出后的未回收状态。被收养后的子进程将来退出,也仍需要收养者领取状态。
因此,不能简单说“所有孤儿的 PPID 都是宿主机的 1”。PID 命名空间和 subreaper 会影响具体关系,见 PR_SET_CHILD_SUBREAPER。
容器中的 PID 1 为什么值得单独检查?
假设业务程序在容器中处于 PID 1,却会继续启动 shell 和工具子进程。如果它没有处理信号与回收,停止容器或结束子任务时就可能留下问题。
可以让业务程序正确管理子进程,或者使用合适的轻量 init。重点不是“多加一个进程就解决”,而是确认谁收养、谁回收、谁转发退出信号。
排查时可以查看 PID、PPID 和状态。Z 表示僵尸是常见线索,但修复前应确认父进程的生命周期与业务影响。
面试官继续追问
收到 SIGCHLD,只 wait 一次够吗?
不一定。多个子进程可能在处理前都已经退出,信号通知也不应当成“一次对应一个结果”。通常需要循环回收当前可领取的子状态。
孤儿一定会很快退出吗?
不会。它可以继续运行,是否退出取决于自身行为、信号和资源,而不是仅由父进程消失决定。
僵尸很少,可以不处理吗?
少量短暂僵尸可能是正常回收窗口;持续积累则说明生命周期管理存在漏洞。看持续时间和增长趋势,而不是只看一次截图。
面试速记卡
- 僵尸:已退出,退出状态尚未被领取。
- 孤儿:原父进程退出,子进程被重新收养。
- kill:不能让已退出的僵尸再次退出。
- 修复对象:优先检查父进程的 wait 与异常路径。
- 容器:明确 PID 1 的信号和子进程回收职责。
公司面试真题
真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。
字节跳动 · 后端(抖音) · 社招
孤儿进程和僵尸进程有什么问题?(题意整理)
社招一年半面经分享 · 抖音部分 ↗
历史面经,面试年份未明确;页面编辑于 2024-07-19