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种状态之间切换?本质是因为进程在“抢资源”,而资源只有两种:
- ** CPU资源 **:就是“打饭窗口”,谁抢到谁就能“运行”;
- ** 外设资源 **:就是“勺子、餐盘”这类,比如键盘、鼠标、硬盘、网络等。
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
非常感谢您的阅读,喜欢的话记得三连哦 |