当前位置: 首页 > news >正文

Linux操作系统从入门到实战(十九)进程状态

Linux操作系统从入门到实战(十九)进程状态

  • 前言
  • 一、什么是进程状态
  • 二、状态本质
  • 三、最核心的3种状态
    • 1. 就绪状态
    • 2. 运行状态
    • 3. 阻塞状态
  • 四、状态变化的核心
    • 1/两种资源如何影响状态?
  • 五、操作系统怎么管理这些状态?
  • 六、Linux里结构体与状态
  • 七、回顾:“父进程”和“子进程”
  • 八、僵尸进程
    • 1. 什么是僵尸进程?
    • 2. 僵尸进程是怎么产生的?
    • 3. 看个例子:30秒的僵尸进程
    • 4. 僵尸进程的危害
  • 九、孤儿进程
    • 1. 什么是孤儿进程?
    • 2. 孤儿进程会变成僵尸吗?
    • 3. 看个例子


前言

  • 上一篇博客里我们讲解了Linux里面怎么查看进程
  • 这篇博客我们开始讲解进程状态与僵尸和孤儿进程

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482


一、什么是进程状态

  • 前面我们讲过可以把“进程”理解成“正在运行的程序”(比如你打开的微信、浏览器,本质上都是一个或多个进程)。

而==“进程状态”==,就是这个“正在运行的程序”当前的“处境”——它现在是在干活?还是在等东西?还是准备好了就等机会干活?

简单说:进程状态就是用来描述“这个进程现在能干啥、接下来要干啥”的标记

二、状态本质

听起来好像很复杂,但其实在电脑(操作系统)内部,** 进程状态就是一个简单的数字 **

比如:操作系统可能用“0”表示“准备好了”,用“1”表示“正在干活”,用“2”表示“在等东西”。不同的操作系统数字可能不一样,但核心逻辑都差不多——用数字标记“进程当前的状态”。

三、最核心的3种状态

所有操作系统(不管是Windows、Linux还是手机系统),管理进程状态的逻辑都差不多,最核心的就3种状态:** 就绪状态、运行状态、阻塞状态 **。

在这里插入图片描述

我们可以用一个生活例子理解:把“进程”比作“去食堂打饭的同学”,“CPU(电脑的核心)”比作“打饭窗口”。

1. 就绪状态

比如你到了食堂,发现窗口正在有人打饭,你就站在队伍里等着——这时候你就是“就绪状态”。

对应到进程:

  • 进程已经把所有“准备工作”做好了(比如需要的内存、数据都齐了);
  • 就差“CPU(打饭窗口)”有空了,一旦CPU轮到它,它就能立刻开始干活。

2. 运行状态

当窗口空出来,轮到你打饭了——这时候你就是“运行状态”。

对应到进程:

  • 进程正在被CPU“处理”,比如正在执行代码(算数学题、处理文字等);
  • 只要CPU没“轮到下一个”,它就一直处于这个状态。

3. 阻塞状态

假设你打饭时发现没勺子,得先去旁边取勺子,这时候你就暂时离开队伍,等拿到勺子再回来排队——这时候你就是“阻塞状态”。

对应到进程:

  • 进程暂时没法用CPU干活,因为它在等“外设资源”(比如等键盘输入、等硬盘读写数据、等网络传输完成);
  • 必须等外设资源准备好了(比如你拿到勺子),它才会重新回到“就绪状态”(回到队伍),再等CPU来处理。

四、状态变化的核心

为什么进程会在这3种状态之间切换?本质是因为进程在“抢资源”,而资源只有两种

  1. ** CPU资源 **:就是“打饭窗口”,谁抢到谁就能“运行”;
  2. ** 外设资源 **:就是“勺子、餐盘”这类,比如键盘、鼠标、硬盘、网络等。

1/两种资源如何影响状态?

  • 如果你是“计算密集型”任务(比如跑复杂的数学公式、处理大数据):主要抢CPU资源,大部分时间要么在“运行”(用CPU),要么在“就绪”(等CPU)。
  • 如果你是“IO密集型”任务(比如用微信发消息、用浏览器下载文件):主要抢外设资源(发消息要等网络,下载要等硬盘),大部分时间可能在“阻塞”(等外设),偶尔回到“就绪”和“运行”。

五、操作系统怎么管理这些状态?

操作系统会给每个CPU建一个“调度队列”(就像食堂的队伍)

  • 所有“就绪状态”的进程,都会排在这个队列里,等着CPU来“叫号”;
  • 一旦CPU“叫到”某个进程,这个进程就从“就绪”变成“运行”;
  • 如果运行中的进程需要等外设(比如等你输入文字),就会离开队列,进入“阻塞”;等外设准备好了,再重新回到“就绪队列”排队。

六、Linux里结构体与状态

最后简单提一下Linux系统里的实现。

在Linux中,每个进程的信息(包括状态、占用的资源、位置等)都存在一个叫“PCB(进程控制块)”的结构体里(可以理解成“进程的身份证+档案”)

  • 结构体就像一个“抽屉”,里面有很多“小格子”(成员),每个格子存不同的信息(比如状态、内存地址等)。
  • 如果你知道某个“小格子”(比如状态这个数字)的地址,就能反推出整个“抽屉”(结构体)的起始地址(就像知道抽屉里某本书的位置,就能找到整个抽屉在哪)。
  • 想访问结构体里的信息(比如状态),直接用“结构体变量.成员名”就行(比如“进程档案.状态”)。

七、回顾:“父进程”和“子进程”

就像现实中父母会生孩子,一个进程(比如你打开的浏览器)也能“创建”新的进程(比如浏览器新开的标签页进程)。我们把“创建者”叫** 父进程 ,“被创建的”叫 子进程 **。

它们的关系就像:父进程“管”子进程,子进程干完活后,要告诉父进程“结果咋样”(比如“任务完成”或“出错了”)。

八、僵尸进程

1. 什么是僵尸进程?

简单说:子进程已经退出(“死了”),但父进程一直没“问”它“死之前干得咋样”,这时候子进程就变成了僵尸进程

用生活例子类比:
你(子进程)帮爸妈(父进程)做一件事,做完后你告诉爸妈“我完事了”,但爸妈一直在忙别的,没理你。这时候你虽然“任务结束”了,但还得等着爸妈回应,就像“僵尸”一样,没彻底“消失”。

2. 僵尸进程是怎么产生的?

子进程退出时,会留下一个“退出状态码”(比如“0”表示成功,“1”表示失败),这个码是给父进程看的。

  • 如果父进程及时用wait()(可以理解成“询问结果”)读取了这个码,子进程就会彻底消失;
  • 但如果父进程没读(比如父进程在睡觉、忙别的),子进程就会保持“僵尸状态(Z状态)”,留在系统的“进程表”里,等着父进程来“处理”。

3. 看个例子:30秒的僵尸进程

有一段代码(不用看懂细节,知道逻辑就行):

  • 父进程创建子进程后,自己睡30秒(期间不处理子进程);
  • 子进程创建后,只睡5秒就退出了。

这时候:

  • 子进程5秒后“死了”,留下退出状态码;
  • 父进程还在睡觉(30秒),没读这个码;
  • 所以子进程在这25秒(30-5)里,就成了僵尸进程,状态是Z。

4. 僵尸进程的危害

僵尸进程虽然“死了”,但它的“档案”(PCB,之前讲过的“进程身份证+信息表”)还在系统里存着——因为要保留“退出状态码”等信息,等着父进程来取。

问题来了:

  • 一个僵尸进程的PCB占一点内存,看起来不多;
  • 但如果父进程创建了很多子进程,还都不管(不读状态码),就会有一堆僵尸进程的PCB占内存,最后导致“内存泄漏”(内存被白白浪费,用不了)。

九、孤儿进程

1. 什么是孤儿进程?

和僵尸进程相反:** 父进程先退出(“死了”),但子进程还在运行,这时候子进程就成了孤儿进程 **。

生活例子类比:
爸妈(父进程)提前“离开”了,你(子进程)还没长大(还在运行),这时候你就成了“孤儿”。

2. 孤儿进程会变成僵尸吗?

不会。因为操作系统有“兜底机制”:
当父进程先死,子进程会被系统的“1号进程”(可以理解成“系统大管家”,比如Linux里的init进程)“领养”。

  • 1号进程会负责“接管”这个孤儿进程,等它退出后,及时读取它的退出状态码;
  • 所以孤儿进程退出后,不会变成僵尸,会被1号进程彻底“清理”掉。

3. 看个例子

一段代码逻辑:

  • 父进程创建子进程后,自己只睡3秒就退出了;
  • 子进程会睡10秒才退出(比父进程活得久)。

这时候:

  • 父进程3秒后“死了”,子进程还在运行,成了孤儿;
  • 系统的1号进程会“领养”这个孤儿;
  • 10秒后子进程退出,1号进程会及时读取它的状态码,子进程正常消失,不会变僵尸。
类型产生原因结果/危害系统处理方式
僵尸进程子进程先死,父进程没读它的退出码留在进程表,占内存,可能导致内存泄漏父进程用wait()读取状态码即可清除
孤儿进程父进程先死,子进程还在运行不会变僵尸,会被1号进程领养并正常回收1号进程接管,负责后续清理

以上就是这篇博客的全部内容,下一篇我们将继续探索Linux的更多精彩内容。

我的个人主页
欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482

非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述

http://www.lryc.cn/news/617238.html

相关文章:

  • JS-第二十三天-正则
  • 大数据量下分页查询性能优化实践(SpringBoot+MyBatis-Plus)
  • 集成电路学习:什么是URDF Model统一机器人描述格式模型
  • ZeroNews:如何构建安全(无需 V*N!)的工业物联网连接
  • 大模型落地:AI 技术重构工作与行业的底层逻辑
  • Salesforce案例:零售企业会员积分体系
  • 【软考架构】需求工程中,系统分析与设计的结构化方法
  • [Shell编程] Shell 编程之免交互
  • C语言模拟 MCU 上电后程序的执行顺序 + 回调函数机制 + 程序计数器(PC)和堆栈的作用
  • LangVM —— 一站式多语言版本管理工具,让 Java、Python、Go、Node.js 切换更丝滑
  • CVE-2019-0708复刻
  • buildroot编译qt 5.9.8 arm64版本踩坑
  • Windows文件时间修改指南:从手动到自动化
  • AI驱动的智能编码革命:从Copilot到全流程开发自动化
  • FFmepg源码系列-avformat_open_input()
  • Python调用C/C++函数库的多种方法与实践指南
  • 聊天室全栈开发-保姆级教程(Node.js+Websocket+Redis+HTML+CSS)
  • MathType关联Wps实现公式编辑【Tex语法适配】
  • 2438. 二的幂数组中查询范围内的乘积
  • 【liunx】web高可用---nginx
  • 编译Android版本可用的高版本iproute2
  • 机器学习 - Kaggle项目实践(1)Titanic
  • C++多态详解
  • SDI设计中,为何SD-SDI模式下,接收器用DRU实现,在3G-SDI模式下,使用transceiver实现
  • 多轮会话记忆的核心挑战
  • Spring Boot 中 @Transactional 解析
  • 自动化备份全网服务器数据平台项目
  • P2865 [USACO06NOV] Roadblocks G
  • ListNode* dummy = new ListNode();什么意思
  • 【功能测试】软件集成测试思路策略与经验总结