Linux进程状态与优先级

        本篇详细的讲解了 Linux 中进程会出现的各种状态,以及出现这些状态的原因,其中进程的阻塞、挂起和运行就是进程状态的体现。接着科普了一下进程的切换,然后讲解了进程的优先级,以及如何调整进程的优先级。最后对进程的特点进行了总结。

目录如下:

目录

1. 进程状态

1.1 R 状态与 S 状态

1.2 T 状态与 t 状态

1.3 D 状态

1.4 Z 状态与 X 状态

1.5 孤儿进程

1.6 进程的阻塞、挂起和运行

2. 进程切换

3. 进程的优先级

3.1 优先级存在的意义        

3.2 优先级的特点

4. 进程的特点的总结

1. 进程状态

        对于 Linux 中的进程,他们存在各种各样的状态,比如正在运行 Run,在休眠状态 Sleep,或者说是已经停止 Stop,其实这样的一些状态也就只是 task_struct 内部属性中的一个变量,用该变量的值来表示当前进程的状态。在进程中存在如下的状态:

static const char* task_state_array[] = {
	"R (runing)",
	"S (sleeping)",
	"D (disk sleep)",
	"T (stopped)",
	"t (tracing stop)",
	"X (dead)",
	"Z (zombie)"
};

        如上的进程状态中,我们只有 D、X 状态无法使用操作来验证,但是其余的操作都可以使用操作来验证。

1.1 R 状态与 S 状态

        R 状态与 S 状态分别标识运行状态休眠状态,我们将使用如下代码来对我们这两种状态进行区分,如下动图:

        (运行状态就是一直在执行进程,而休眠状态就是CPU什么都不干,没有执行进程)

        如上图所示,当我们写了一个无限循环的打印代码,在左框图中查询相关的状态,状态表示:S+,当我们在将打印代码给注释掉了之后,发现状态变为了 R+ 状态。

        关于如上的现象,为什么屏幕一直在打印信息,状态会显示为 S+ (休眠)状态呢?这是因为当我们需要打印信息的时候,是向屏幕上打印出信息,而屏幕上打印信息也就需要屏幕与内存相交互,需要CPU执行过后将数据刷新到内存中,然后屏幕在从内存中拿出数据打印,但是其中存在很大的速度间隔,比如CPU执行完这条数据只需要 1ns,而屏幕从内存中拿出数据却需要 1ms 的实践,所以很多的时候都是CPU在等待屏幕将内存中的数据取完在执行,所以我们在查询状态的时候,有 99% 的可能都是查询到 S 状态,所以我们可以得出关于 S 状态其实是 CPU 一直在等待执行进程的状态,同时也是进程在等待“资源”就绪的状态,因为只有进程资源就绪,才会继续运行。同时这也对应了为什么我们将打印代码给注释掉之后,查询到的进程状态为 R 状态,因为CPU一直在运行这个进程,期间并没有等待。

        那么为什么我们的 S 状态后还跟着一个 “ + ” 呢?这是因为当前进程是在前台运行,当当前进程在后台运行的时候,这个 “ + ” 号也就消失了,想让程序在后台执行,我们只需要在执行文件的指令后面加上一个 & 符号即可,如下:

        如上操作,当前进程的状态就从 S+ 变成了 S 状态,关于前台后台运行状态的区别,将会在后面给出。(后台运行的进程不能用 ctrl + c 终止进程,只能用 kill -9 pid)

1.2 T 状态与 t 状态

        现在将进入 T 状态,关于 T 状态就是将当前运行的进程停止运行,进程变为等待运行状态,如下:

        当我们使用 kill -19 pid 的时候,我们就将该进程给暂停掉了,当我们使用 kill -18 pid 的时候,又将进程给再次启动了。当程序进入暂停状态的时候,程序就不会在继续运行了,只有当我们使用指令将其唤醒,才会继续运行。

        那么当我们在对程序进行调试的时候,进程又是处于什么状态呢?,如下所示:

        当我们使用 gdb 对程序进行调试的时候,状态从 S 状态变为了 t 状态,t 状态叫做追踪暂停,也就是当我们进行调试打断点的时候,就会出现 t 状态,运行到断点处暂停下来,就是 t 状态

1.3 D 状态

        D 状态是 Linux 系统中特有的一个状态,是一种特殊的休眠状态。由于这个状态我们并不能掩饰,所以用例子来给出:

        当我们的进程想要调度磁盘给我们写入大量数据的时候,磁盘接收到了这个消息,然后磁盘便开始向内写入数据,提出申请的进程便进入了 S 状态。但当前的内存中的空间十分的紧张,内存出现严重不足的情况,Linux 操作系统此时有权杀掉内存中的部分进程来腾出空间。假设这时刚好将等待磁盘给出回应的进程给删除了,当磁盘写入数据失败的时候,会给进程一个响应,是再一次写入还是直接丢弃。但此时进程都已经被杀掉了,磁盘根本找不到进程,然而其他进程又需要使用磁盘,此时磁盘就将刚刚写入的数据给丢弃了,这份数据就丢失了,也就造成了数据丢失的事故。

        所以为了防止这样数据丢失的情况,也就出现了 D 这种状态,这种状态被叫做深度睡眠(不可中断睡眠)。结束这种状态只有两种方法:自己醒来或者重启。

1.4 Z 状态与 X 状态

        Z 状态下的进程我们也叫做僵尸进程,出现这种的情况的原因是,当我们的子进程运行完自己的程序后,按道理应该将子进程的数据代码以及在操作系统中的 task_struct 给删除的,但是此时父进程并没有将子进程给回收,没有被回收也就意味着进程的数据代码从内存中删除了,但是内核数据结构 task_struct 还在操作系统中,并没有被释放掉。如下:

        如上所示,当我们的子进程结束后,而父进程还未结束,这就会导致子进程进入僵尸进程。关于僵尸进程,并不是会一直处于僵尸进程,也是会被回收的,task_struct 进程中记录着自己退出的信息,未来让父进程读取。但是也会存在一些情况,父进程异常结束,那么子进程的僵尸进程会一直存在

        当我们的僵尸进程未来被 waitpid 接口读取了,这个进程就会由 Z 状态变成 X 状态,就会被回收了。

1.5 孤儿进程

        孤儿进程,就是当父进程已经退出,但是子进程还并没有退出,这时候的子进程就是孤儿进程。如下所示:

        如上图所示,当我们的父进程运行结束后,子进程的 ppid 变为了 1,也就是说子进程的父进程改变了,这是为什么呢?这时因为,当父进程先退出,而子进程并未退出,也就意味着子进程未来不会被回收,会变成僵尸进程,但是操作系统为了防止这种情况发生,就自己将孤儿进程领养了,用来保证子进程被正常的回收

        通过以上也可以得出,只有在父进程结束的时候,才会回收子进程,但是我们平时在命令行运行的程序,为什么不会出现僵尸进程的情况呢?这是因为命令行启动的进程的父进程是 bash,bash 会自动的回收新进程的僵尸进程

1.6 进程的阻塞、挂起和运行

        首先我们先介绍进程的运行状态,也就是 R 状态(上面所讲的为在 task_struct 中的出现的状态),现在我们将从操作系统层面讲解运行状态。如下图:

        在操作系统中,每个CPU都有着一个对应的运行队列,当我们需要执行某个进程的时候,就是将该进程对应的 task_struct 进入运行队列,然后将对应的代码和数据传入到CPU中进程运行,此时只要进程在运行队列中,那么该进程就是处于运行状态

        关于进程一旦持有CPU,CPU不会直到将该进程运行结束才运行下一个进程,这是因为在内核数据结构 task_struct 中有着一个时间片,记录着该进程最多被CPU运行多少时间,当时间到了的时候,就会将该进程给列入到队尾,运行下一个进程,循环往返。这样让多个进程以切换的方式进行调度,在一个时间段内得以同时推进代码的方式,叫做并发。(这是调度算法的一种, Linux 中不是这样调度的)

        关于我们进程的阻塞状态,应该对应于以上进程的哪种状态呢?就比如当我们需要从键盘中读入数据的时候,只有读完数据之后,才能继续运行我们的进程,所以等待键盘读入是一种阻塞,如下:

        如上所示,当我们需要从键盘中读入一个数据的时候,左边的检测窗口检测出进程的状态为 S 状态,所以 S 状态属于一种阻塞态。(其实 D 状态也是阻塞态,但是我们不能演示出来)

        关于阻塞状态的底层实现:其实对于各种设备的管理,也是使用数据结构将其描述组织起来的,该数据结构中包括当前设备的类型、状态、已经对应的设备结构体指针(用于将各个设备给链接起来)等等,还有一个等待队列,这个等待的队列的作用是,当某些进程需要从设备中读入数据的时候(比如使用 sancf 函数从键盘读取设备,在磁盘中给进程读入数据),操作系统就会将正在运行队列中的 task_struct 从运行队列中剥离,然后将其放入到设备的等待队列中,等到从设备中读取数据成功之后,才将 task_struct 放回到运行队列中。所以对于以上这种情况的状态,就叫做阻塞状态。

        最后是我们的挂起状态,如下图:

        在磁盘中存在一个 swap分区,当我们的内存特别吃紧的时候,操作系统会将处于 S 状态,也就是处于阻塞状态的进程的代码和数据放入到swap分区中去,然后腾出空间给其他需要的进程,但是这样并不是将一个进程给删除了,因为该进程的 task_struct 还在操作系统中,只是将他的数据放入到了磁盘中去,这个操作叫做换出,当阻塞状态结束的时候,在将进程的代码和数据换入回内存中。这种状态叫做阻塞挂起态。其实关于以上这个将暂时不需要的数据放入到磁盘中,需要的时候在将数据从磁盘中换入的状态就叫做挂起态

        关于这样的挂起态,其实会导致一定的效率问题,因为这样不断的换入换出,会花部分时间在 IO 写入和写出中,所以对于我们的 swap分区来说,一般并不会有太大的空间,因为太大空间会导致 OS 依赖该空间,频繁的用该空间挂其进程,导致效率变低。

2. 进程切换

        关于我们进程的切换,CPU 正是通过频繁地对不同的进程进行运行,来达到在用户层面上很多进程同时进行的现象,所以说在 CPU 内进程会频繁的进行切换,当在进程切换的时候,有可能是因为当前进程已经运行结束,也有可能是当前进程的时间片已经结束,该下一个进程的运行了。

        当一个进程的时间片结束运行下一个进程的时候,我们需要将进程进行切换,但当前这个进程并没有运行结束,而是运行了部分,所以我们需要将未运行结束的数据给保存起来,然后当下一次运行到这个进程的时候,我们将之前保存的数据在调出来,然后继续的运行。在 CPU 中用于存储数据的元件叫做寄存器,每个CPU只有一套的寄存器,这些寄存器中的临时数据叫做上下文数据,当我们需要切换的时候,将换走进程的数据放入的 task_struct 保存起来,将换入进程的数据从 tast_struct 中读入。

3. 进程的优先级

        上文中所讲的进程分别进入到 CPU 的运行队列中,运行队列按照先进先出的方式,分别按顺序地运行不同的进程,不同进程在运行队列前的排队,其本质就是确定获取 CPU 资源的顺序,所以进程之间的优先级就是获取某种资源的先后顺序。 

        在内核数据结构 task_struct 中存在一个内部字段 --> int priority = ?? ,表示当前进程的优先级,其中 priority 数值越小,优先级越高

3.1 优先级存在的意义        

        对于大多的普通的电脑设备而言,CPU 只有一个,也就是一段时间内只能运行一个进程,所以说进程访问资源(CPU)始终都是有限的。所以说需要对进程之间创建一个优先级,决定哪些进程先运行,提高运行队列。

        操作系统中关于调度和优先级的原则:分时操作系统,分时间片对不同的进程进行运行,这样可以维持基本的公平。若进程因为长时间不被 CPU 调度,就造成了进程饥饿的问题。

3.2 优先级的特点

        在 Linux 中,我们使用指令:ps -al,查看当前所有运行的进程的优先级,如下:

        PRI:进程优先级;

        NI:进程优先级的修正值,nice值;

        进程优先级 = 优先级 + nice值,只要修改 nice 值就可以达到对进程优先级修改的过程。那么我们使用什么指令对进程的优先级做调整呢?

        我们在命令行中输入 top 指令,然后输入 r 指令,输入我们要调整优先级的 pid,然后在输入我们要调整的 nice 值,如下:

        如上所示,当我们进行如上步骤时,先将 nice 值调整为100,我们查看时,也只是发现调整的 nice 值为19,优先级从80变成了99,当我们将 nice 值调整为-100的时候,也只是发现nice值变成了-20,从99变成了60,所以对于我们nice值的范围是-20~19,最多只能将 niec 调整为19,最低调整为-20,默认进程的优先级从80开始调整。

4. 进程的特点的总结

        进程还存在一些其他的特点,如下:

        1. 并发与并行:关于并发,就是多个进程在一个CPU下采用进程切换的方式,在一段时间内(也就是基于时间片来运行程序),让多个进程都得以推进。对于并行,就是一个电脑中存在多个CPU,多个进程在多个CPU下分别,同时的运行。

        2. 进程的独立性:多个进程的运行,每个进程都是相互独立的,都独享着自己的各种资源,运行期间不会相互干扰。(某个进程运行出现异常,也不会影响到其他进程)

        3. 竞争性:系统的进程数目较多,而CPU资源只有少量(通常为1个),所以进程之间是具有竞争属性的,为了高效的完成任务,更合理竞争相关资源,就出现了进程的优先级。

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

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

相关文章

C语言自定义类型中结构体、结构体声明、结构体自引用、结构体变量的定义和初始化、结构体内存对齐,结构体传参,位段等的介绍

文章目录 前言一、结构体二、 结构体声明三、 特殊的声明----匿名结构体类型四、 结构体的自引用(1)数据结构(2)结构体的自引用 五、 结构体变量的定义和初始化六、 结构体内存对齐1. 结构体的对齐规则(1)结…

华为eNSP综合实验-网络地址转换

实验完成之后,在AR1的g0/0/1接口抓包,查看地址转换 实现私网pc访问公网pc 实验命令展示 SW1: vlan batch 12 #创建vlan interface e0/0/1 #进入接口配置vlan端口 port link-type access port default vlan 12 q interface e0/0/2 #进入接口配置vlan端口 port link-type ac…

iphone忘记锁屏密码怎么解锁?这些解锁方法你必须知道!

在使用iPhone的过程中经常会遇到很多问题,比如忘记了iPhone的锁屏密码。面对这样的情况,许多用户可能会感到手足无措。别担心,本文将为您详细介绍iPhone忘记锁屏密码的解锁方法,让您轻松解决这一烦恼。 一、使用iTunes备份恢复 如…

盘点一下4种常见的微信的广告类型,在微信上打广告要花多少钱?

微信是一款社交媒体应用,集Facebook、Instagram和Snapchat的功能于一身。该应用拥有超过12亿的月活跃用户,其中约7亿为日活跃用户。由于其在中国网民中的成功和广泛的通信工具,微信是推广您业务的绝佳平台。 在这篇博客文章中,我…

Centos7完全卸载与安装mysql8.0+

Centos7卸载与安装mysql8.0 1、mysql8完全卸载2、mysql8安装 1、mysql8完全卸载 sudo systemctl stop mysqldsudo yum remove mysql-community-serversudo rm -rf /var/lib/mysql sudo rm -rf /etc/my.cnfsudo groupdel mysql sudo userdel mysqlsudo rm -rf /var/log/mysql s…

nginx代理原理(端口复用)探究

前言:对于一些常用的插件,我们应该学会如何使用。同时,其实现原理也要进行深究,可以为其他的项目开发做借鉴。 探究方案: 一、发布两个不同的服务,这两个服务的端口不致 二、配置nginx,让这两…

3W 3KVDC 隔离单、双输出 DC/DC 电源模块——TPH-3W 系列

TPH-3W系列是一款3W,单、双输出隔离电源模块,特别适合板上只有一种电压而要求有正负电源的场合,工业级温度范围–40℃到105℃,在此温度范围内都可以稳定输出2W,并且效率非常高,高达86%,温升非常低&#xff…

剁手党必看——转转红包使用规则与最优组合计算全解析

​ 1、省钱攻略基础之“了解平台红包使用规则” 2、举个栗子 3、最优红包组合计算方法进化过程 3.1、初代“笛卡尔乘积”版 3.2、二代“边算边比较Map聚合”版 3.3、三代“边算边比较数组索引定位”版 4、总结 1、省钱攻略基础之“了解平台红包使用规则” 规则一&#x…

浙大×移动云,携手点亮AI新时代

近年来,中国移动依托强大的算网资源优势,围绕大模型训练、推理和应用三大场景,打造了一站式智算产品体系。该体系旨在为客户提供覆盖资源、平台、应用的AI全链路服务。目前,一站式智算产品体系已在浙江大学智算中心和许昌中原智算…

后端常用技能:基于easy-poi实现excel一对多、多对多导入导出【附带源码】

0. 引言 在业务系统开发中,我们经常遇到excel导入导出的业务场景,普通的excel导入导出我们可以利用 apache poi、jxl以及阿里开源的easyexcel来实现,特别easyexcel更是将excel的导入导出极大简化,但是对于一些负载的表格形式&…

新能源汽车热管理方案现状与未来发展趋势

前言 新能源汽车的热管理技术在提高电池寿命、提高能量利用效率和确保车辆运行安全方面起着至关重要的作用。 一 新能源汽车热管理技术方案 1 电池热管理系统 电池热管理系统是电动汽车中至关重要的一部分,它通过冷却液循环、加热器、散热片等方式控制电池温度&…

【解决Android Studio】cmake报错找不到vulkan包

1 报错信息 CMake Error at D:/Android/project/cmake/3.10.2.4988404/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:137 (message): Could NOT find Vulkan (missing: Vulkan_LIBRARY) Call Stack (most recent call first): 2. 错误原因 minSdk版本不对&am…

【Linux网络编程】DNS、ICMP、NAT技术、代理服务器+网络通信各层协议总结

DNS、ICMP、NAT技术、代理服务器网络通信总结 1.DNS2.ICMP协议2.1ping命令2.2traceroute命令 3.NAT技术4.NAT和代理服务器5.网线通信各层协议总结 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励&…

uniapp 小程序图片懒加载组件 ImageLazyLoad

预览图 组件【ImageLazyLoad】代码 <template><viewclass"image-lazy-load":style"{opacity: opacity,borderRadius: borderRadius rpx,background: background,transition: opacity ${time / 1000}s ease-in-out,}":class"image-lazy-loa…

白话机器3:PCA与SVM详细数学原理

一、PCA数学原理 1.数据标准化 首先&#xff0c;需要对原始数据进行标准化处理&#xff0c;使得每个特征的均值为0&#xff0c;方差为1。假设有一个的数据矩阵X&#xff0c;其中每一列是一个样本&#xff0c;每一行是一个特征。 标准化公式如下&#xff1a; 其中&#xff0c;…

Observability:监控与可观察性不同的 3 个原因

作者&#xff1a;来自 Elastic Elastic Observability Team 监控和可观察性通常可以互换使用&#xff0c;但它们并不完全相同。 监控是可观察性的重要组成部分&#xff0c;但可观察性远远超出了传统监控实践的范围。 主要区别&#xff1a;监控从各个组件收集数据 —— 时间和内…

【北京迅为】《iTOP-3588开发板快速烧写手册》-第8章 TF启动

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

PyQt:进度条实现(下载、复制)实时进度显示

一、实现思路 源文件:①被复制的文件&#xff08;一般在客户端自身PC上&#xff09;&#xff1b;②被下载的文件&#xff1b;&#xff08;一般在服务器上&#xff09;。 缓存文件&#xff1a;正在粘贴/下载获取中的文件&#xff0c;粘贴/下载完成前&#xff0c;一般是不完整的…

什么是CE认证?

目录 一、什么是CE认证&#xff1f; 二、CE认证对于企业来说有什么重要性&#xff1f; 三、企业在申请CE认证时&#xff0c;需要满足哪些条件和要求&#xff1f; 一、什么是CE认证&#xff1f; CE认证&#xff0c;即只限于产品不危及人类、动物和货品的安全方面的基本安全要…

鸿蒙内核源码分析(信号消费篇) | 谁让CPU连续四次换栈运行

本篇有相当的难度&#xff0c;涉及用户栈和内核栈的两轮切换&#xff0c;CPU四次换栈&#xff0c;寄存器改值&#xff0c;将围绕下图来说明. 解读 为本篇理解方便&#xff0c;把图做简化标签说明: user:用户空间kernel:内核空间source(…):源函数sighandle(…):信号处理函数&a…