Linux进程状态及优先级

news/2024/5/18 19:35:22/文章来源:https://blog.csdn.net/m0_73446322/article/details/130495252

进程状态及优先级

本文已收录至《Linux知识与编程》专栏!
作者:ARMCSKGT
演示环境:CentOS 7

在这里插入图片描述


进程状态及优先级

  • 前言
  • 正文
    • 进程状态
      • 就绪运行状态R
      • 阻塞
        • 睡眠状态 S
        • 休眠状态D
        • 挂起
      • 暂停状态T
        • 前台与后台进程
        • 待追踪暂停状态t
      • 死亡状态 X
      • 僵尸状态 Z
    • 孤儿进程
    • 进程优先级
      • 查看进程优先级
      • 修改进程优先级
  • 最后


前言

操作系统想管理好进程并不简单,对于Linux系统将进程分为不同的状态进行管理;例如运行,阻塞,休眠状态等等,每一种状态都有不同的效果,这样才能发挥他的全部功效,且进程之间也有优先级,本文将为您详细讲解!
进程状态图


正文

进程状态


为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。

进程状态

下面是进程状态在kernel源代码中的定义:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

分别对应:

  • R(就绪运行状态)
  • 阻塞状态
    – S(睡眠状态/可中断睡眠状态)
    – D(休眠状态/不可中断休眠状态)
    – 挂起状态
  • T(暂停状态)
    – 前台/后台进程
    – t(待追踪暂停状态)
  • X(死亡状态)
  • Z(僵尸状态)


就绪运行状态R

虽然从字面理解,运行状态就是进程在CPU上运行,但并非如此!
R(运行状态)代表进程在运行队列中排队,而队列的维护是操作系统来做的;可以理解为进程就绪,等待CPU资源的状态!

#include <iostream>
using namespace std;int main()
{while(true); //死循环return 0;
}

test
在Linux系统中,新建、就绪、运行都可以看作运行 R 这一个状态,清晰明了!



阻塞

阻塞进程因为等待某种条件就绪,而导致的一种不推进状态,也就是进程卡住了;阻塞一定是在等待某种资源!
为什么会阻塞?进程要通过等待的方式,等具体的资源被别的进程用完之后,再被自己使用。

简而言之:阻塞就是进程等待某种资源(磁盘,网卡,显卡等各种外设)就绪的过程。

当一个进程运行到某指令时需要外部资源时,操作系统会将进程就会撤出CPU,放到某种资源处进行排队,也就不在CPU上运行了,直到该进程获取到了所有资源(具备运行条件),操作系统会将此进程放入运行队列中进行排队,继续运行!

综上:进程PCB可以被维护在不同的资源队列中; 所以阻塞就是不被调度,一定是因为当前进程需要等待某种资源就绪;在Linux系统下,一定是task_struct结构体需要在某种被操作系统管理的资源下排队!


睡眠状态 S

睡眠状态是可中断休眠,是阻塞的一种

当进程需要某资源时,操作系统将该进程挂到对应的资源队列排队,此时进程处于可中断休眠状态!

#include <iostream>
using namespace std;
>#include <unistd.h>int main()
{while(true) //死循环打印pid{cout<<getpid()<<"进程运行中..."<<endl;sleep(1);}return 0;
}

可中断休眠
这里可能会有小伙伴疑惑,进程在运行,为什么不是显示R,而是S+?
这里需要说明一下的是,进程向屏幕不断打印的行为也是I/O行为,需要向屏幕这个硬件进行写入,所以每次申请写入屏幕时需要到对应资源队列排队并处于休眠状态,而CPU的运行速度非常快,在此过程中,进行几万次捕捉可能就只有一两次看到进程处于R状态,其他时候都是S+状态。

可能小伙伴还有一个问题,那么S+状态的 + 是什么意思?这个 + 的意思是代表该进程在前台运行,具有体前台后台进程的区别在暂停状态会简单介绍!

处于可中断休眠状态的进程可以被CTRL+C或kill -9等信号终止进程!
CTRL+C发送2号信号


休眠状态D

休眠状态是不可中断休眠状态,也是阻塞的一种!

休眠状态下的进程无法别终止,kill信号和操作系统都无法终止,只能等待进程获取到了对应的资源(达到对应条件)才能终止休眠状态; 当然,通过切断电源的方式也可以强制关闭,但是那样操作系统也关闭了,且会损失数据!

这种状态一般可能出现在,例如进程需要在磁盘上I/O,但是此时磁盘I/O阻塞了,此时如果影响进程可能会造成数据损坏,所以操作系统为了保证数据安全,不会插手这件事,一般很少会碰到该状态,如果碰到了该状态,那么计算机很可能就要崩溃了!

所以这种状态的出现往往是为了保护进程,但是最好尽量避免出现这种状态!


挂起

挂起一般又称阻塞挂起,也是一种特殊的阻塞状态!

当系统资源紧张,某些进程在运行时等待资源阻塞时,操作系统保留PCB转而释放该程序的代码和数据(放到硬盘上)腾出空间,此时进程被挂起。



暂停状态T

我们可以使用kill信号的方式让进程进入暂停状态;进入暂停状态的进程不在运行并保持在后台!

使进程暂停的方法:SIGCONT信号

  • kill -19 进程PID (暂停进程)
  • kill -18 进程PID (恢复进程)
    暂停状态T

前台与后台进程

在Linux系统下,当进程在前台运行时其状态会附带一个 +,代表该进程是前台进程!
如果是后台进程则没有 + 符号!
进程可以在不同的状态下处于前台和后台运行!
前台与后台


待追踪暂停状态t

该状态是指该进程正在被另一个进程跟踪,例如在Linux下通过GDB调试一个程序,GDB中对被跟踪的进程打一个断点,进程在断点处停下来的时候就处于 t 状态。而在其他时候,被跟踪的进程还是处于其他。对于进程本身来说,T 和 t 状态很类似,都是表示进程暂停下来。
gdb



死亡状态 X

当进程结束或被终止时进入死亡状态,这个状态只是一个返回状态,你不会在任务列表里看到这个状态。因为CPU的处理速度非常快,这只是一瞬间!



僵尸状态 Z

僵尸状态是一个与死亡状态相似的状态,通常来说僵尸状态给父进程所准备的!

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵死(尸)进程。僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

当父进程创建子进程后,子进程已经运行结束,父进程需要去接收子进程的退出结果(返回值)来判断子进程是否正常运行或运行结果是否正常,然后回收子进程!

所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。

#include <iostream>
using namespace std;
#include <unistd.h>
#include <cstdlib>int main()
{pid_t id = fork();if(id == 0){int i = 10;while(i--){cout<<"子进程运行中..."<<endl;sleep(1);}cout<<"子进程退出!"<<endl;exit(0);}int i = 20;while(i--){cout<<"父进程运行中..."<<endl;sleep(1);}cout<<"父进程退出!"<<endl;return 0;
}

子进程僵尸状态
维护僵尸进程的意义是为了让父进程读退出码,但是僵尸进程也有以下等危害:

  • 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态。
  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护。
  • 那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费;因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
  • 既然进程一直在内存中保存,就可能存在内存泄漏,需要释放。

所以我们要避免子进程长时间处于僵尸状态,后面在进程控制中会讲解回收监视子进程的办法!


孤儿进程


当父进程先于子进程结束或终止时,子进程就成为孤儿进程!
在Linux系统中,孤儿进程由1号进程bash接管成为后台进程!
孤儿进程
为什么bash要接管这个孤儿进程?

  • 如果不接管那么子进程在结束后没有父进程回收,一直处于僵尸状态,造成内存泄漏,所以需要bash接管进行释放!

进程优先级


进程除了有不同的状态,还有优先级之分:

  • cpu资源分配的先后顺序,就是指进程的优先权(priority)。
  • 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
  • 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

CPU的资源是有限的,合理分配才能最大化效能!
Linux 给我们提供了修改 进程 优先级的权限,目的就是让我们对多任务运行进行合理处理,提高系统运行效率。


查看进程优先级

ps指令可以加上 -al 选项显示进程的其他信息!

ps -al | head -1 && ps -al | grep 进程名(程序名) | grep -v grep

进程优先级查看
关于PRI与NI值
– PRI是进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。

PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:(新的PRI)=(旧的PRI)+nice

– NI是nice值,其表示进程可被执行的优先级的修正数值。

– 当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux下,就是调整进程nice值。

nice其取值范围是-20至19,一共40个级别;当我们设置nice值时超过这个区间是无效的!

– 这里需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。可以理解nice值是进程优先级的修正修正数据。

– 优先级的修改行为并不是连续的,每次都是在最开始的基础上进行修改(默认为 80)。

– 调度器不允许存在 优先级失衡 的情况,因此优先级修改不能太激进。



修改进程优先级

进程优先级可以修改,但一般我们是不干预操作系统的调度的!

修改步骤:

  • top指令打开Linux任务管理器
  • 输入 r 进入NI值修改模式
  • 输入想修改NI值进程的PID
  • 最后输入NI值即可(范围-20~19)

步骤:
1
2
3
4
2
动图演示:进程优先级修改


最后

进程状态和进程优先级的知识到这里就介绍的差不多了,通过了解进程状态,知道进程的阻塞和和运行的原理;了解进程优先级,学习了修改进程的优先级影响调度机制,这些知识都在为后面进程控制的学习打下基础,后面我们还会介绍有关Linux的环境变量相关知识,敬请期待!

本次 <Linux进程状态及优先级> 就先介绍到这里啦,希望能够尽可能帮助到大家。

如果文章中有瑕疵,还请各位大佬细心点评和留言,我将立即修补错误,谢谢!
结尾

🌟其他文章阅读推荐🌟
Linux<进程初识> -CSDN博客
C++ <STL之string的使用> -CSDN博客
C++ <模板> -CSDN博客
C++ <内存管理> -CSDN博客
🌹欢迎读者多多浏览多多支持!🌹

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_296884.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Java虚拟机学习》 java代码的运行过程

1. Java文件转换 当我们保存java文件后&#xff0c;首先由编译器编译成class文件&#xff0c;然后通过Java虚拟机将class文件转换成字节码文件 2.Java虚拟机是怎么运行Java文件 首先将java文件加载到java虚拟机中&#xff0c;然后由虚拟机将类元信息存储在 虚拟机的方法区中。…

华为OD机试 - 各位相加(Java)

一、题目描述 给定一个非负整数 num&#xff0c;反复将各个位上的数字相加&#xff0c;直到结果为一位数。 二、思路与算法 各位相加&#xff0c;使用递归&#xff0c;出口是结果的长度等于1。 三、Java算法源码 public static int addDigits(int num) {recursion(num);re…

Maven 3.9.1下载安装配置一条龙(无压力)亲测

这里写自定义目录标题 前言一、下载 Apache Maven 3.9.11.1、请先检查自己的IDEA是否有这个条件&#xff0c;是否兼容1.2、Maven下载 二、Windows安装配置Maven2.1、解压2.2、新建 repository 本地仓库2.3、配置环境变量MAVEN_HOME 软件路径M2_HOME 本地仓库路径配置Path2.3.1新…

【BIM+GIS】Supermap打开BIM Revit模型的方式

Revit导出Supermap GIS格式数据的方法通常有三种:插件式导出、直接导入和标准交换格式(IFC)导出。 文章目录 一、Revit安装Supermap插件1. 安装Supermap插件2. UDB导出模型3. 打开模型二、Revit导出IFC格式1. Revit导出IFC2. Supermap导入IFC一、Revit安装Supermap插件 1. …

【TCP 重传、滑动窗口、流量控制、拥塞控制】

文章目录 重传机制超时重传快速重传SACK方法Duplicate SACK 滑动窗口流量控制那操作系统的缓冲区&#xff0c;是如何影响发送窗口和接收窗口的呢&#xff1f;窗口关闭 拥塞控制慢启动拥塞避免拥塞发生快速恢复 重传机制 TCP 实现可靠传输的方式之一&#xff0c;是通过序列号与…

大学校友会管理APP系统开发 重温同学梦再叙校园情

互联网技术的深入发展&#xff0c;让各行各业对网络的依赖都逐渐加深&#xff0c;可以说网络在今天已经成为无数个你我他不可或缺的平台。学生时代是一生中最美好的时期&#xff0c;校友是社会高效重要的社会资本和无形资产&#xff0c;校友与校友之间信息交流也需要依靠互联网…

破事精英2◎爬向未来

胡强的2033未免有些过去可怕&#xff0c;海星果然又是反派。 只剩“脑子”的胡强 400百斤只剩“嘴”的庞小白 将自己身体分成一个个“方块”的苏克杰 苍蝇满天飞“衣服堆”的金若愚 “脑子”送到月球打两份工的沙乐乐 有机器人或者分身帮我们干活赚钱&#xff0c;我们去吃喝玩…

Dubbo源码篇02---从泛化调用探究Wrapper机制的原理

Dubbo源码篇02---从泛化调用探究Wrapper机制的原理 什么是泛化调用从传统三层架构说起反射调用尝试优化 泛化调用泛化调用怎么用通过Spring使用泛化调用 利用泛化调用改造现有服务 泛化调用小结 Wrapper机制自定义代理dubbo底层wrapper原理小结 小结 什么是泛化调用 从传统三层…

JVM(类的加载与ClassLoader、双亲委派机制)

文章目录 1. 类的生命周期2. 类的加载过程3. 类加载器&#xff08;classloader)3.1 类加载器的作用3.2 类加载器的分类(JDK8)3.3 双亲委派机制3.3.1 双亲委派机制优势 3.4 查看某个类的类加载器对象3.5 使用ClassLoader获取流 1. 类的生命周期 类在内存中完整的生命周期&#…

【移动端网页布局】flex 弹性布局 ④ ( 设置子元素是否换行 | flex-wrap 样式说明 | 代码示例 )

文章目录 一、设置子元素是否换行 : flex-wrap 样式说明1、flex-wrap 样式引入2、flex-wrap 样式取值说明 二、代码示例1、代码示例 : 默认情况下 flex 弹性布局子元素不会自动换行2、代码示例 : 自动换行 一、设置子元素是否换行 : flex-wrap 样式说明 1、flex-wrap 样式引入 …

拿来吧你——一个类帮你搞定SpringBoot中的请求日志打印

拿来吧你——一个类帮你搞定SpringBoot中的请求日志打印 日常开发工作中避免不了要打印请求日志&#xff0c;这个功能几乎在所有的项目中都需要编写一次&#xff0c;重复的次数多了&#xff0c;难免会感觉繁琐&#xff0c;因此打算搞一个通用类把这块功能拆出来。 废话不多说—…

【Android车载系列】第12章 车载渲染-SurfaceFlinger单独绘制到界面

1 SurfaceFlinger渲染方案 车载的倒车影像同学们知道是怎么实现的吗&#xff1f;等待Android设备开机再打开倒车影像App&#xff1f;车子挂到R档倒车如果等待这个流程实在太久&#xff0c;是否还有其它办法可以让车子挂R档直接展示倒车影像呢&#xff1f;大家思考一下。 我们从…

SuperMap GIS基础产品WebGIS FAQ集锦(2)

SuperMap GIS基础产品WebGIS FAQ集锦&#xff08;2&#xff09; 【iClient】Vue中该如何使用inject传递Map容器&#xff1f; 【解决方案】provide和inject绑定是不可响应的&#xff0c;所以传递时需要传递对象的property&#xff0c;使它变为可响应&#xff0c;示例如下&#…

ESP32-设备驱动TMP102数字温度传感器驱动

TMP102数字温度传感器驱动 文章目录 TMP102数字温度传感器驱动1、TMP102介绍2、硬件准备3、软件准备4、驱动实现1、TMP102介绍 TMP102 器件是一款数字温度传感器,非常适合需要高精度的 NTC/PTC 热敏电阻更换。 该器件提供 0.5C 的精度,无需校准或外部组件信号调理。 器件温度…

Redis --- 多级缓存

一、什么是多级缓存 传统的缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未命中则查询数据库&#xff0c;如图&#xff1a; 存在下面的问题&#xff1a; 请求要经过Tomcat处理&#xff0c;Tomcat的性能成为整个系统的瓶颈Redis缓存失效时&#xff…

Java集合之单列集合

分类 集合分为单列集合&#xff08;Collection&#xff09;和双列集合&#xff08;Map&#xff09; 单列集合的体系结构 List集合和Set集合的区别 List系列集合&#xff1a;添加元素是有序的&#xff08;添加的顺序&#xff0c;而非数据的大小顺序&#xff09;、可重复、有索引…

基于springboot的医院信管系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&…

【STM32】定时器PWM模式详解

PWM模式&#xff1a; PWM模式1&#xff0c;向上计数时&#xff0c;PWM信号从有效电平变为无效电平 PWM模式2&#xff0c;向上计数时&#xff0c;PWM信号从无效电平变为有效电平 PWM极性&#xff1a; 极性为高时&#xff0c;高电平为有效电平&#xff0c;低电平为无效电平 极性…

酷游浅谈网站Javas cript型别

最近整理了一下&#xff0c;【酷游娜娜手机&#x1d54d;找看看nay3989提供】就决定跟大家讨论一下最近对于Javascripet的型别认识。 弱型别&#xff36;&#xff33; 强型别 Javascripet是一种「弱型别」的语言&#xff0c;所以会产生很多你意想不到恶心的事情 至于什么是弱…

基于Redis优化验证码登录流程, 解决登录状态刷新问题

文章目录 1 问题: 多台Tomcat间session共享问题2 Redis代替session的业务流程分析2.1 设计key的结构2.2 设计Key的具体细节2.3 整体访问流程 3 基于Redis实现短信登录4 解决状态登录刷新问题4.1 初始方案问题4.2 优化方案4.3 代码 1 问题: 多台Tomcat间session共享问题 书接上…