僵尸进程和孤儿进程

僵尸进程

(1)简介

  • 在操作系统中,僵尸进程(Zombie Process)是指已经终止执行的进程,但其父进程还没有调用 wait() 系统调用来获取其退出状态的进程。虽然这个进程已经停止了,但它的进程描述符仍然在操作系统的进程表中。

  • 僵尸进程的存在主要是为了保存其退出状态,以便父进程稍后可以获取。一旦父进程调用 wait() 来获取子进程的退出状态,操作系统就会释放僵尸进程的所有资源。

  • 如果父进程没有正确地处理僵尸进程,那么这些僵尸进程可能会在系统中积累,导致资源浪费。因此,父进程通常需要负责定期调用 wait() 等待子进程的终止。

(2)示例

  • 在多进程的情境下,如果创建了子进程,而主进程没有适时地等待子进程结束,就有可能出现僵尸进程。以下是一个示例:
from multiprocessing import Process
import time
import os
def task():
print(f"子进程 {os.getpid()} 开始执行")
time.sleep(3)
print(f"子进程 {os.getpid()} 执行完毕")
if __name__ == '__main__':
# 创建子进程
p = Process(target=task)
p.start()
# 主进程不等待子进程,直接结束
# 此时子进程可能成为僵尸进程
print("主进程结束")
# 主进程结束
# 子进程 17904 开始执行
# 子进程 17904 执行完毕
  • 在这个示例中,主进程启动了一个子进程,但主进程没有等待子进程结束,而是直接结束。这种情况下,子进程可能成为僵尸进程。在实际应用中,通常会使用 p.join() 或其他手段来等待子进程的结束,以防止僵尸进程的产生。

(3)僵尸进程的危害

僵尸进程的存在可能导致一些问题和危害,这主要是因为僵尸进程占用系统资源并且不能正常释放。以下是僵尸进程可能引发的一些问题:

  1. 资源浪费: 僵尸进程会占用系统进程表等资源,尽管它们已经完成执行。这可能会导致系统资源的浪费,特别是在创建大量进程的情况下。
  2. 进程表溢出: 操作系统维护着一个进程表,其中包含所有活动进程的信息。僵尸进程占用了进程表中的一个槽位,如果僵尸进程过多,可能导致进程表溢出,使得系统无法再创建新的进程。
  3. 父进程信息泄漏: 僵尸进程仍然保留有关其父进程的一些信息,如父进程的PID。这可能导致敏感信息泄漏,尤其是在某些安全敏感的应用程序中。
  4. 降低系统性能: 大量的僵尸进程可能导致系统性能下降,因为操作系统需要花费额外的时间和资源来维护这些僵尸进程。
  5. 进程号枯竭: 如果系统中存在大量的僵尸进程,可能会耗尽可用的进程号,导致新进程无法创建。

为了避免这些问题,父进程通常需要调用 wait()waitpid()join() 等方法来等待子进程的正常退出,从而确保子进程成为僵尸进程的时间尽可能短暂。合理的进程管理和终止策略是保持系统稳定和高效运行的关键。

(1)解决办法

  • 一:杀死父进程
  • 二:对开启的子进程应该记得使用join,join会回收僵尸进程

孤儿进程

(1)简介

  • 孤儿进程(Orphan Process)是指一个子进程在其父进程终止后,由操作系统接管的进程。在 Unix-like 操作系统中,这是通过将孤儿进程的父进程更改为 init 进程(进程ID为1)来实现的。

  • 孤儿进程(Orphan Process)是指一个子进程在其父进程终止后,由操作系统接管的进程。在 Unix-like 操作系统中,这是通过将孤儿进程的父进程更改为 init 进程(进程ID为1)来实现的。

  • 当一个进程创建子进程后,通常会等待子进程执行完成。但如果父进程在子进程执行期间先于子进程结束而终止,子进程就会变成孤儿进程。操作系统会接管孤儿进程,并将其父进程设置为 init 进程。

  • init 进程是系统引导过程中启动的第一个用户级进程,负责启动和管理系统的其他进程。因此,孤儿进程成为 init 进程的子进程,init 进程会负责回收孤儿进程的资源。

(2)示例

  • 指一个子进程在其父进程终止后,由操作系统接管的进程。
import os
import sys
import time
if __name__ == '__main__':
# 获取当前进程的PID(父进程的PID)
pid = os.getpid()
ppid = os.getppid()
print('我是父进程 :>>> ', 'pid', pid, 'ppid', ppid)
# 使用 os.fork() 创建子进程
pid = os.fork()
# os.fork() 返回两次,父进程中 pid 是子进程的 PID,子进程中 pid 是 0
if pid > 0:
# 在父进程中
print('父进程终止')
sys.exit(0) # 父进程终止,子进程被 init 进程(PID=1)接管
# 在子进程中,pid 为 0
# 为确保主线程退出完毕,睡眠1秒
time.sleep(1)
print('我是子进程 :>>>> ', os.getpid(), os.getppid())
# 注意:由于 sys.exit(0) 终止了父进程,因此子进程继续执行

image

本文作者:ssrheart

本文链接:https://www.cnblogs.com/ssrheart/p/17970414

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ssrheart  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起