僵尸进程和孤儿进程
僵尸进程
(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)僵尸进程的危害
僵尸进程的存在可能导致一些问题和危害,这主要是因为僵尸进程占用系统资源并且不能正常释放。以下是僵尸进程可能引发的一些问题:
- 资源浪费: 僵尸进程会占用系统进程表等资源,尽管它们已经完成执行。这可能会导致系统资源的浪费,特别是在创建大量进程的情况下。
- 进程表溢出: 操作系统维护着一个进程表,其中包含所有活动进程的信息。僵尸进程占用了进程表中的一个槽位,如果僵尸进程过多,可能导致进程表溢出,使得系统无法再创建新的进程。
- 父进程信息泄漏: 僵尸进程仍然保留有关其父进程的一些信息,如父进程的PID。这可能导致敏感信息泄漏,尤其是在某些安全敏感的应用程序中。
- 降低系统性能: 大量的僵尸进程可能导致系统性能下降,因为操作系统需要花费额外的时间和资源来维护这些僵尸进程。
- 进程号枯竭: 如果系统中存在大量的僵尸进程,可能会耗尽可用的进程号,导致新进程无法创建。
为了避免这些问题,父进程通常需要调用 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) 终止了父进程,因此子进程继续执行
本文作者:ssrheart
本文链接:https://www.cnblogs.com/ssrheart/p/17970414
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具