【Linux 学习计划】-- 进程状态 | 进程运行、阻塞和挂起的本质 | 并行、并发与进程切换 | 进程优先级

article/2025/8/7 11:33:46

目录

进程状态

五状态进程模型

运行、就绪状态的本质

阻塞状态的本质

挂起状态

并行与并发

进程切换

进程优先级

结语


进程状态

进程状态的本质是什么?

首先我们知道,在操作系统中,进程是需要被管理起来的,具体则是用一个struct(task_struct)描述进程本身,接着再用内核数据结构将所有的进程管理起来,这也就是所谓的先描述,再组织

而我们的进程状态,本质就是task_struct里面的其中一个属性,仅此而已(比如是一个个的int)

这就是内核中关于进程状态的描述

接下来我们详细讲讲这里面的 7 个进程状态

第一个是R状态

首先需要提前说的是,我们在Linux中是可以用指令查到进程状态的,也就是ps命令

我们来看这样一个代码,我们可以看到这其实就是一个死循

然后当我们将进程跑起来之后,我们再来看一看这个进程的状态:

我们可以看到,这里显示的确实是R(R+中的+代表前台执行,不需要管)

这其实也就代表说,当进程处于R状态的时候,代表进程正在运行或者准备运行

S状态

S状态表示进程正在可中断睡眠状态,简称睡眠状态,s也就是sleep

来看这样一组代码:

我们能看到,这里和死循环的唯一区别就是,他有在打印一行字符串

这时我们将进程跑起来,然后看看进程状态:

我们能看到,仅仅只是将加了一行打印,就变成了一直在睡眠

这其实是因为,我们CPU运行速度过快,而我们的显示器是外设,将数据拷贝到外设的速度比CPU的运算速度慢多了,所以进程大部分的时间并不是在运行,而是在等数据拷贝到显示器上,然后再运行

所以从理论上来说,如果我们运气好的话,是能看到一两个R状态的,只不过主包今天运气不是很好,就不做演示了

T状态

可以看到,我们现在用kill命令将进程停止了之后,进程的状态自动就变成了T,这也是停止状态

t 状态(tracing stop)

这个状态其实也是停止,和上面的 T 状态其实差不多

但是这个和 T 不一样的就是,他是调试专属的状态

试想一下,我们的调试本身就是进程已经在跑了,然后我们给他打断点,让他停在某一个位置,所以这其实也是一种进程的暂停,如下图:

左边是在用gdb调试代码,右边显示状态的时候就是 t 状态(前提是gdb是用 r 跑起来的并且打了断点)

z 僵尸进程

什么是僵尸进程呢,先来举一个例子:

如果一个人si了,那么警cha到了之后第一反应应该是封锁现场,等法医过来收集完信息之后,才会清理现场,办理后续的各种事情

而我们的进程也是一样的,如果一个进程没了,那么也需要有进程回收他,而这个进程一般情况下都是父进程(孤儿进程或者waitpid都是os直接回收)

那是否有这么一种情况,父进程还在,但是子进程已经挂掉了,这个时候父进程还没有干完自己的事情,所以是没有办法回收子进程的,只有等父进程也退出之后,才会回收子进程

那如果父进程一直不回收子进程,那么子进程这个时候将会一直是僵尸进程

如下:

我们写一个简单的fork,然后我们再在外面使用kill -9直接将子进程杀掉,这时候再去查看子进程的状态,我们就能看到 Z 状态了

可以看到,当我们将子进程给 kill 掉之后但是父进程一直不回收,这时候子进程将会一直是 Z 状态

而且很关键的一点是,如果我们在未来写了一些项目几万行代码,你甚至都不知道有僵尸进程的问题,那么父进程一直不回收,子进程将会一直 Z,Z 的时候,子进程的代码和数据都没释放掉了,之后对应的task_struct还在,因为要等父进程拿完对应的子进程的信息之后才会被释放

那么,子进程将会一直占用内存资源,这也就造成了一个大问题——内存泄漏

而在未来,我们将会学到使用waitpid等待,最后子进程完成任务退出之后将会被等待,最后直接被os拿信息接着释放,这样就不会内存泄漏了,但这不是今天你的重点,这里就不做讲解了

X状态(死亡状态)

这是一个瞬时状态,只会出现在进程死亡的一瞬间

D状态(不可中断睡眠状态)

这个状态和前面的 S 状态其实多多少少有点联系,这里就讲一个小故事:

当我们有重要的业务的时候,我们的进程就是D状态

比如在银行,如果今天这个进程要将一万个用户的转账数据放到内存中,但是如果放到一般,因为如果没有D的话,那么进程就将是S状态(睡眠),所以如果OS比较紧张的话,那么就有可能将这个进程直接kill掉或者直接打断然后派发其他任务,那么这时候数据就流失了

所以这种时候就是D状态,意味着不可被打断,你就是再怎么紧张,你也不能动我,这就是D

孤儿进程

这是进程的一种,有这么一种情况,也就是,如果父进程没了,但是子进程还在呢?那么子进程这时候如果也没了,那么数据应该被谁回收

首先父进程如果是第一个在程序里被开辟的,那么父进程的父进程就是bash,他会被bash回收,那么这时候子进程就变成了孤儿进程

直接说结论,这时候子进程会被 1 号进程(其实就是bash)领养,最后由bash进行善后处理

五状态进程模型

我们会看到,这个五状态进程模型,和我们上面讲的各种状态一个都对不上啊

其实不是对不上,而是因为本身的性质就不一样

我们的五状态进程模型是理论,而上面说的S、D、t、T等等,这些是Linux的具体实现

比如运行状态和就绪状态,这不就是R吗,阻塞,就是S等等

接下来我们直接来讲一讲,运行状态与就绪状态的本质,阻塞状态的本质,挂起状态的本质

运行、就绪状态的本质

我们来看这样一张图片,首先我们在内存中是有一个runqueue的,也就是运行队列

我们将进程管理起来之后,还需要将等待运行的队列放进runqueue这个内核数据结构中管理起来

这也就代表,只要你是被链进runqueue里面的进程,那么就是就绪和运行状态

当然你也可以这么理解,因为后续进程还需要被放进cpu中执行相关任务,你可以理解成:放在runqueue中但是还不在CPU的就是就绪状态,也就是已经准备好了,等待运行,而被CPU调度的进程则是运行状态

而在Linux中,无论是就绪状态还是运行状态,都是用 R 来表示的

阻塞状态的本质

在我们之前写代码的时候,一定会用过scanf函数

当我们将程序跑起来的时候,如果我们不在键盘上输入数据,那么进程将会一直停在那个地方

这其实就是所谓阻塞状态了,而这个状态下,进程自然就不会停留在runqueue中

那么进程会在哪里呢?

首先我们的外设都是硬件,而操作系统如果要管理外设的话,就需要驱动层的帮助,而驱动层是经过struct描述且用特定数据结构管理起来的软件

而我们外设的驱动中会有这么一个字段,叫做wait_queue(等待队列)

当我们的进程需要用外设参与操作的时候,这时候在我们看来,其实就是阻塞了

而阻塞的进程就不应该再浪费CPU资源了,所以就不能放进runqueue里面,而是会被放进对应驱动软件中的等待队列字段里面

如此一来,当我们的外设完成了对应操作之后,进程重新加载到runqueue中,这就是阻塞状态的本质了

挂起状态

当我们的内存空间过于紧张的时候,就会有挂起状态的出现

我们在磁盘当中有一个区域叫做——swap分区

当我们的磁盘空间严重不足的时候,就会出现这么一个情况:一个进程可能暂时在执行别的不需要他管的任务,或者是一些其他的进程,os 会将他们全部移动到磁盘(外设)的swap分区上
这样省出来的空间,就可以供操作系统做别的事情
等晚些这个进程要被用到的时候,再从swap分区中移动回来

但是这也会导致一个问题,也就是效率

在日常使用的感受就是——卡

因为OS中最消耗时间的就是拷贝数据问题了,现在还要将数据从内存拷贝到外设,要用的时候再从外设拷贝回来,这显然占用了很大一部分的效率

但是注意,这里的前提条件是,内存很紧张,所以这也是一种时间换空间的做法

并行与并发

我们刚刚说到了runqueue,那么进程在操作系统中到底是怎么运行的呢?

我们看到这张图,我们的进程会一个一个地被加载到CPU里面接着进行调度

但是又有不一样的地方,即他是用时间片轮转的方式进行进程调度的

一般来说,如果我们将一个进程调度完之后,才跑下一个进程,那其实不是很合理且不现实

比如我们今天打开一个网易云音乐,这个软件现在正在跑,我们就打开不了其他软件了吗?当然不

所以在OS中,他会给每一个进程一个特定的时间段,过了这个时间段就直接中止这个进程转而执行下一个进程

一直反复这个过程,只要转换的速度够快,我们人其实是察觉不出来的,就达到了每一个软件,每一个进程都在同时跑的效果

这就叫做并发

那么什么是并行呢?

我们上面的并发是只有一个CPU的情况下,很多进程在一个CPU下进行轮转调度

而并发就是现在不止一个CPU,由多个CPU同时在进行进程轮转调度的工作,这就是所谓并行了

进程切换

这个其实是接着并行与并发这两个知识点的,我们要讨论的是,进程的并发是如何进行的

我们来看这张图,首先我们进程要想加载到CPU中的话,数据是必须要拷贝到CPU中的

而CPU中的寄存器就可以暂时保存这些数据

接着,当我们这个进程运行到一半的时候,突然时间到了,他需要被切换了,那么他就需要将这些数据全部保存下来,不然的话,下次再轮到他的时候,不就相当于没跑过吗

为了保存这些数据,所以我们的PCB也就是task_struct中有专门的结构体类型,就是用来保存上下文数据的

当我们要切换进程的时候,CPU里面的寄存器的数据就会被拷贝到task_struct中的特定字段,然后再运行下一个进程

等到下一次再回到这个进程的时候,就可以将上一次保存下来的上下文数据全部放进去继续跑了

这就是所谓进程切换了

将个故事:你是一名大学生,今天你想去当兵,那么你就需要先和辅导员打个招呼,这就相当于是将CPU中寄存器的数据加载进进程的特定字段中,然后你就去入伍了。两年回来以后,你会学校还是要和辅导员打个招呼,接着就是恢复学籍数据等等,这一步其实就是将进程中的数据重新加载回CPU进行调度了

进程优先级

顾名思义,就是哪个进程最先调度

更重要的进程就需要更高的优先级

那么和上面的进程状态一样,进程的优先级其实也只是进程PCB里面的一个字段而已,这个我们可以在命令行中直接查看到:

(使用的是 ps -al 命令)

但是这里面有两个值得注意的字段:一个是最新的优先级的值,还有一个就是nice值:

这也就意味着,我们的进程优先级是可以更改的,只不过更改的方式只是更改nice值

这里更改nice值有很多方式,比如renice,但是主包这里直接用 top -> r -> 进程pid -> 你要的nice值

但是我们可以看到,这里面的优先级最多就是到了99,而nice值则是19

这是因为我们的nice值是有范围的,也就是 -20~19

再加上默认的进程优先级就是80,所以进程优先级的范围就是 60~99

结语

这篇文章到这里就结束啦!!~( ̄▽ ̄)~*

如果觉得对你有帮助的,可以多多关注一下喔


http://www.hkcw.cn/article/GkljaoBggb.shtml

相关文章

自证式推理训练:大模型告别第三方打分的新纪元

1. 传统验证体系的困境与技术跃迁的必然性 1.1 传统验证器的局限性 现有强化学习框架依赖显式验证器对答案进行二值化判定,这种模式在数学、代码等可验证领域表现优异。某厂内部数据显示,传统R1-Zero方法在代码生成任务中准确率达92%,但切换…

《操作系统真相还原》——加载器

显存 将上一章的中断输出,变为显存输出 加载器 使用mbr引导程序从磁盘中加载loader程序。 MBR %include "boot.inc" SECTION MBR vstart0x7c00 mov ax,cs mov ds,axmov es,axmov ss,axmov fs,axmov sp,0x7c00mov ax,0xb800mov gs,ax;cl…

Spring Boot 应用中实现配置文件敏感信息加密解密方案

Spring Boot 应用中实现配置文件敏感信息加密解密方案 背景与挑战 🚩一、设计目标 🎯二、整体启动流程 🔄三、方案实现详解 ⚙️3.1 配置解密入口:EnvironmentPostProcessor3.2 通用解密工具类:EncryptionTool 四、快速…

前端实现图片压缩:基于 HTML5 File API 与 Canvas 的完整方案

在 Web 开发中,处理用户上传的图片时,前端压缩可以有效减少服务器压力并提升上传效率。本文将详细讲解如何通过<input type="file">实现图片上传,结合 Canvas 实现图片压缩,并实时展示压缩前后的图片预览和文件大小对比。 一、核心功能架构 我们将实现以…

用wireshark抓了个TCP通讯的包

昨儿个整理了下怎么用wireshark抓包&#xff0c;链接在这里&#xff1a;捋捋wireshark 今天打算抓个TCP通讯的包试试&#xff0c;整体来说比较有收获&#xff0c;给大家汇报一下。 首先就是如何搞到可以用来演示TCP通讯的客户端、服务端&#xff0c;问了下deepseek&#xff0c;…

AWS WAF设置IP白名单

目标 设置一个组白名单IP地址&#xff0c;当发现是这些IP地址发过来的请求后&#xff0c;WAF自动放行。 创建IP集 打开WAF页面&#xff0c;开始IP集创建如下图&#xff1a; 设置ip集&#xff0c;如下图&#xff1a; aws waf acl配置白名单 找到Web ACL&#xff0c;开始在…

随笔20250530 C# 整合 IC卡读写技术解析与实现

以下是一个完整、最简化的 FeliCa 读取整合示例&#xff08;无需 SDK&#xff0c;基于 PCSC NuGet 包&#xff09;&#xff0c;你可以直接运行这个控制台程序&#xff0c;验证能否识别 RC-S300 并读取卡片 UID&#xff1a; &#x1f9ea; 示例说明 &#x1f4e6; 使用 NuGet 包…

day024-网络基础-TCP与UDP、DNS

文章目录 1. 李导推荐书籍2. OSI七层模型2.1 传输层2.2 网络层2.2.1 问&#xff1a;两端处于不同局域网的设备怎么网络通信&#xff1f; 2.3 数据链路层2.4 物理层2.5 图解OSI七层模型 3. 数据传输模式3.1 全双工3.2 半双工3.3 单工 4. TCP 3次握手4.1 抓包 5. TCP 4次挥手5.1 …

AI赋能开源:如何借助MCP快速解锁开源项目并提交你的首个PR

引子 很多同学都梦想为开源项目贡献力量&#xff0c;然而现实往往是——面对庞大复杂的项目&#xff0c;从入门到提交第一个有实质性代码的PR&#xff0c;时间跨度可能长达数年。传统路径通常是先从文档贡献开始&#xff0c;逐步深入理解项目架构&#xff0c;最终才能进行代码…

智能问数技术路径对比:NL2SQL vs NL2Semantic2SQL

在人工智能浪潮席卷数据分析领域的当下&#xff0c;“智能问数”凭借其自然语言交互的便捷性&#xff0c;迅速成为企业提升数据民主化与决策效率的焦点。大语言模型&#xff08;LLM&#xff09;展现出的强大语言理解和生成能力&#xff0c;无疑为这一愿景启动了引擎。 然而&am…

QT-Creator安装教程(windows)

目录 1&#xff0c;下载 1.1 镜像源下载 1.2 运行下载的exe文件 1.2.1 QT5 版本安装 1.2.2 QT6 版本安装 1.2.3 如何在安装完成之后&#xff0c;继续添加扩展包 1&#xff0c;下载 1.1 镜像源下载 地址&#xff1a;Index of /qtproject/ 根据电脑系统选择下载linux、macO…

Warm-Flow发布1.7.3 端午节(设计器流和流程图大升级)

Warm-Flow发布1.7.3 端午节&#xff08;设计器流和流程图大升级&#xff09; 更新内容项目介绍功能思维导图演示地址官网Warm-Flow视频 更新内容 [feat] 新版流程图通过前端渲染[perf] 美化流程设计器ui[feat] 办理人权限处理器&#xff0c;新增办理人转换接口&#xff0c;比如…

分布式锁Redisson使用

redission为我们提供了方便使用redis集群的方法&#xff0c;可以使用它完成锁的建立。 依赖 <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.36.0</version></dependency>spring引…

Unity UI系统中RectTransform详解

一、基础代码示例 public GameObject node; var rect node.GetComponent<RectTransform>();Debug.Log($"anchoredPosition----{rect.anchoredPosition}"); Debug.Log($"offsetMin.x--{rect.offsetMin}"); Debug.Log($"offsetMax.x--{rect.of…

神经网络(Neural Networks)

设计神经网络的最初动机是编写能够模仿人类大脑学习和思考方式的软件。现今&#xff0c;神经网络也被称为人工神经网络&#xff0c;其工作方式已经与我们所认为的大脑实际工作方式和学习方式大不相同。 研究神经网络的工作始于 20 世纪 50 年代&#xff0c;之后的一段时间它并不…

DeepSeek‑R1-0528 重磅升级:蚂蚁百宝箱免费、无限量调用

DeepSeek‑R1-0528 重磅升级&#xff1a;蚂蚁百宝箱免费、无限量调用 端午假期前一天&#xff0c;DeepSeek‑R1 更新到了 0528 版本&#xff01; 官方说明&#xff1a;0528 版本在深度思考与推理能力方面显著增强——在数学、编程与通用逻辑等多项基准测评中&#xff0c;表现已…

可定制化货代管理系统,适应不同业务模式需求!

在全球化贸易的浪潮下&#xff0c;货运代理行业扮演着至关重要的角色。然而&#xff0c;随着市场竞争的日益激烈&#xff0c;货代企业面临着越来越多的挑战&#xff1a;客户需求多样化、业务流程复杂化、运营成本上升、利润空间压缩……这些挑战迫使货代企业不断寻求创新和突破…

使用基于Xsens惯性传感器的动作捕捉技术测量人体工程学

由于单调和片面的体力消耗&#xff0c;牙科领域的从业者患肌肉骨骼疾病 (MSD) 的几率很高。惯性测量单元 (IMU) 越来越成为评估工作姿势风险的焦点。因此&#xff0c;本研究旨在使用基于惯性传感器的运动捕捉 (MoCap) 评估人体工程学讲座和培训干预对牙科助理学生的姿势风险和M…

设计模式之结构型:桥接模式

桥接模式(Bridge Pattern) 定义 桥接模式是一种​​结构型设计模式​​&#xff0c;通过​​将抽象部分与实现部分分离​​&#xff0c;使它们可以独立变化。它通过组合代替继承&#xff0c;解决多层继承导致的类爆炸问题&#xff0c;适用于​​多维度变化​​的场景(如形状与颜…

Spring Boot 3 整合 MQ 构建聊天消息存储系统

引子 在构建实时聊天服务时&#xff0c;我们既要保证消息的即时传递&#xff0c;又需要对消息进行持久化存储以便查询历史记录。然而&#xff0c;直接同步写入数据库在高并发场景下容易成为性能瓶颈&#xff0c;影响消息的实时性。秉承"没有什么问题是加一层解决不了的&q…