操作系统面试题 — 什么是孤儿进程和僵尸进程,如何处理它们?

0 阅读3分钟

Author : Cyan_RA9
Source : 【卡码笔记】网站
Question : 什么是孤儿进程和僵尸进程,如何处理它们?

【简要回答】

  1. 孤儿进程(Orphan Process)
    • 定义:父进程已终止,子进程仍在运行,这些子进程被称为 孤儿进程,最终会被 init 进程(PID=1)接管并回收。
    • 处理方法:通常无需手动处理,由 init 进程自动回收。
  2. 僵尸进程(Zombie Process)
    • 定义:子进程已终止,但父进程未通过 wait() 读取其退出状态,导致 PCB 残留。
    • 处理方法:父进程调用 wait()waitpid() 主动回收;若父进程无法修改,则终止父进程使其由 init 回收。

【详细回答】

  1. 孤儿进程(Orphan Process)
    • 定义
      父进程意外终止(如崩溃、被 kill)先于子进程退出,子进程仍在运行,这些子进程被称为 孤儿进程,操作系统将其父进程重置为 init(PID=1)。
    • 产生原因
      父进程未等待子进程结束(如未调用 wait())便提前终止
      父进程因错误(如段错误、未处理信号)意外退出
    • 系统影响
      通常对系统无害,但若孤儿进程长时间运行且未正确释放资源(如未关闭文件句柄、未释放共享内存),可能导致资源泄漏。
    • 处理方法
      无需手动处理init 进程会自动接管并调用 wait() 回收孤儿进程。
  2. 僵尸进程(Zombie Process)
    • 定义
      子进程已终止(通过 exit() 或信号),但其退出状态未被父进程读取,内核保留其 PCB 直至父进程调用 wait()
    • 产生原因
      父进程未调用 wait()waitpid() 回收子进程。
      父进程未注册 SIGCHLD 信号处理函数,或处理函数未正确回收所有子进程。
    • 系统影响
      占用有限的 PID 资源(Linux 默认 PID 上限为 32768),导致系统资源浪费,极端情况下导致新进程无法创建。
      残留的 PCB 可能干扰进程监控工具(如 pstop)的统计信息。
    • 处理方法
      ① 父进程调用 wait()waitpid() 回收子进程资源。
      ② 若父进程不处理,可终止父进程,由 init 进程接管并回收僵尸进程。
      ③ 使用信号处理函数(如 SIGCHLD)自动回收子进程。

【知识拓展】

  1. 僵尸进程示意图如下
    Zombie_Process.jpg
  2. 僵尸进程案例:Python 异步爬虫系统的“资源泄露”
    • 场景: 某公司开发了一个分布式的网页爬虫系统。主程序(父进程)负责调度,每当发现一个新的 URL,就通过 subprocess 模块启动一个下载进程(子进程)去抓取内容。
    • 发生过程: 程序员在代码中只负责启动子进程,但由于没有写 process.wait() 或者没有处理 SIGCHLD 信号,当下载进程抓取完数据正常退出后,父进程并没有去“收尸”。
    • 后果: 由于爬虫任务极多,服务器在运行 24 小时后,ps -aux 发现系统中出现了数千个状态为 Z (Zombie) 的进程。最终,服务器报错 "No more processes"
  3. 孤儿进程案例:被遗忘的数据库“导出大户”
    • 运维人员小王通过 SSH 登录到生产服务器,手动执行了一个超大型的数据库备份脚本:mysqldump -u root ... > backup.sql。这个任务预计要跑 5 个小时。
    • 发生过程: 小王执行完命令后,因为网络抖动,他的 SSH 连接断开了。此时,启动该脚本的父进程(Bash 终端)因为连接断开而自杀了。
    • 结果: 这个 mysqldump 进程瞬间变成了孤儿进程。幸好 Linux 的内核很聪明,立刻让 PID 为 1 的进程(systemdinit)收养了它,它得以在后台继续跑完。