【Linux】进程状态与优先级

news2025/1/12 15:49:24

文章目录

      • 进程状态概念
      • Linux中的进程状态
        • R(running)状态
        • S(sleeping)状态
        • D(disk sleep)状态
        • T(stopped)状态
        • t(tracing stop)状态
        • X(dead)状态
        • Z(zombie)状态
        • 特殊的孤儿进程
      • 进程优先级
      • 进程性质补充

进程状态概念

《现代操作系统》中给出的进程状态的定义如下:

进程状态反映进程执行过程的变化。这些状态随着进程的执行和外界条件的变化而转换。在三态模型中,进程状态分为三个基本状态,即运行态就绪态阻塞态。在五态模型中,进程分为新建态终止态运行态就绪态阻塞态

这里不讲什么三态五态模型,

只是从一个相对通俗的角度去看待一下进程状态。

首先理解一个简单的问题,

一个进程开始运行是一直占用CPU资源到进程结束吗?

就从我们的电脑能同时运行时几个进程就可以看出答案肯定是否定的。

所以多个进程已经具备被CPU调度的条件之后,

也就是进程就绪之后,

可以简单认为进程会进入一个操作系统维护的运行队列中,

在这个运行队列中排队等待被调度,

当进程运行够一段时间之后再放到队尾排队等待下一次调度,

此时下一个位于队头的进程继续被CPU调度,

所以进程在运行的过程中会经历不断地进程切换,

在这个运行队列中的进程,就是上述所说的就绪态和运行态

但是与此同时还有一个问题就是,

如果运行中的进程要访问外设,

需要向外设输入输出呢?

因为向外设的io行为相比CPU的运行效率,

实在是太低了!

CPU如果等的话效率会大大降低!

就比如在银行排队办理业务时,

排到你的时候需要你填一张表,

工作人员是让你去旁边填完表再过来,继续为后面的客户办理业务,

还是就让你当场填,等填完再继续呢?

大部分情况下都会是选择前者。

操作系统也是这么想的!

当一个进程要访问外设时,

操作系统会将这个进程移出运行队列

此时就可以说这个进程处于阻塞状态

当然,进程进入到阻塞状态并不一定都是因为访问外设。

但是资源是有限的啊,

如果内存一旦不足,

操作系统作为管理者定不会坐视不管,

而处在运行队列中的进程肯定不好被清理,

而处于阻塞状态的进程呢?

进程对应的代码和数据暂时并用不到,

是否可以考虑暂时将进程对应的代码和数据移出内存呢?

确实可以,操作系统也确实是这么做的。

我们就可以称进程被挂起了

综上,我们主要介绍了操作系统宏观层面的进程状态,这里做一个小小的总结。

我们主要介绍了运行、阻塞和挂起。

一个进程正在运行,不一定是正在占用CPU资源,

也有可能是在等待被CPU调度。

而正在被调度的进程,可能因为有IO操作或其他系统服务请求,

而因为某些原因请求无法立即完成,

为了让CPU资源得到最大的释放,

操作系统选择将等待请求的进程调出运行队列,

此时就可以说进程处于一个阻塞状态。

而当内存资源不够用的时候,

操作系统又会将“不那么着急的进程”的数据和代码调出内存从而缓解资源不足,

此时又可以说进程被挂起了。

操作系统宏观层面的概念介绍得差不多了,

下面介绍一下Linux下的几种进程状态。


Linux中的进程状态

上面主要介绍了操作系统层面宏观的进程状态,

下面就具体到Linux操作系统中看看进程状态是怎么体现出来的。

首先进程状态是一种数据,

数据就要存储,

而他又是进程的一种属性,

进程的属性数据存放在哪呢?

当然是PCB中啦,也就是task_struct中。

下面的状态在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运行状态(running) : 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。

S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。

D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。

T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。

X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态

当我们使用ps axj命令查看进程时,标红的那一列就是进程状态;

image-20230110150902988

S就是运行状态,+ 表示的是在前台运行,

前台运行后台运行的区别后面会进行演示。

下面就介绍几种容易被捕捉到的进程状态。


R(running)状态

R状态是运行状态。

前面提到了,

处于R状态的进程并不代表正在被CPU调度,

也有可能是在运行队列中排队。

所以进程状态所提到的就绪态和运行态就是这里的R状态。

一般是只有计算需求的进程才会长时间处于R状态,

只要是有IO行为的进程很大概率都不会被观察到在R状态。

为什么?下面给出答案。


S(sleeping)状态

S状态是睡眠状态,

准确地说应该是浅度睡眠状态,

是可以被中断的一种状态,

同时也是阻塞的一种情况。

怎么让一个进程进入浅度睡眠呢?

换句话说,怎么让一个进程处于阻塞状态呢?

最简单粗暴的方法就是,

直接调用sleep接口,

但是这样太无趣了,

不妨试试先面的代码,

观察一下生成的可执行程序运行时的进程状态:

int main()
{
    while (1)
    {
        printf("我是一个进程, pid : %d\n", getpid());
    }
    return 0;
}

下面是演示:

进程状态1

左侧这个进程明明一直在运行,

但是右侧却一直显示它处于睡眠状态?!

在介绍阻塞状态的时候说过,

当进程有IO行为时,

因为IO效率相比CPU的运行效率差太多了,

所以当进程要访问外设时CPU为了不耽误时间,

就将其移出运行队列进行转移,

此时进程就处于阻塞状态。

这里同理,

我们调用了printf函数,

要向显示器打印,

所以进程大部分时间都处于一个阻塞状态,

也就是这里的S状态,

只有极短的时间内进程才被CPU调度。

在这种情况下我们在某一时刻去观察进程状态,

观察到S状态的概率肯定就很大。

某一时刻肯定能观察到进程处于R状态,

只是概率很低罢了。


D(disk sleep)状态

D状态是深度睡眠状态。

与前面的浅度睡眠状态相比,

处于深度睡眠的进程不可被打断,

只能等IO结束或条件到位才能恢复运行,

即使是操作系统,也不能打断它!

下面用一个小例子去理解为什么会有D状态:

现在有操作系统、进程和磁盘。

进程现在要向磁盘写入大量数据,

在写入的时候进程就什么也不干,

等着磁盘那边发来结束的信号。

而此时内存正好满了,

操作系统需要清理一下门户来释放一些空间。

此时操作系统就找到了这个什么也没干的进程,

就把他干掉了。

而磁盘此时写入失败了,返回失败信息给进程,

但是进程此时已经不在了,

能怪谁呢?

所以对于有高IO需求的进程会长时间处于阻塞状态,

而这种进程又是不能被随便杀掉的,

所以就有了D状态,

处于D状态的进程不能被用户或操作系统挂掉。

而一旦当进程中存在大量处于D状态的进程时,

此时可能就处于一个非常危险的情况了。

因为D状态高IO的需求代价可能比较大,

所以这里就不做演示了。


T(stopped)状态

T状态是暂停状态,也是阻塞的一种。

怎样让一个运行中的进程变成暂停状态呢?

我们可以用kill给进程发暂停信号:

image-20230110160605666

具体就是kill -19 PID

image-20230110161357512

此时进程被暂停了,

而进程状态后面的那个小加号也没了,

此时进程就从前台调到后台了,

当进程重新被唤醒的时候也不会自动调到前台了。

下面用kill指令将进程唤醒看看效果:

kill -18 PID

image-20230110162205821

后台进程相比前台进程,

不能直接用Ctrl C挂掉,

当然也不影响在前台使用各种命令;

image-20230110162349931

但是不怕,我们还有kill

image-20230110162501929

以上就是对暂停状态的介绍,

并稍微认识了一下前台进程和后台进程。


t(tracing stop)状态

t状态是追踪暂停状态。

处于这种状态下的进程会被追踪,

最直观的一个例子就是我们调试代码的时候,

进程会在断点处停止运行,

但是此时进程仍在被追踪,等待下一步指示:

image-20230111002527369


X(dead)状态

X是死亡状态。

死亡状态没什么好说的,

处于死亡状态的进程会被回收,

包括进程控制块和对应的代码和数据,

而回收过程几乎是瞬间完成的,

所以这里很难做出演示。


Z(zombie)状态

Z状态是僵尸状态,

处于Z状态的进程就称其为僵尸进程。

进程运行完毕,无论失败与否,

都要向父进程或操作系统返回结束信息,

当父进程或操作系统收到结束信息后会对进程进行清理工作。

而如果父进程或操作系统长时间没有接收结束信息,

或接收信息后没有对进程进行清理,

会发生什么呢?

此时进程已经运行完了,

但是进程没有被清理,

至少PCB还留在内存中占用资源,

而这也就造成了资源的浪费。

下面用一个简单的例子来演示一下僵尸进程:

int main()
{
    int id = fork();
    if (id > 0)  //父进程
    {
        while (1);
    }
    else if (id < 0)  //进程创建失败
    {
        perror("fork");
        exit(-1);
    }
    else  //子进程
    {
        sleep(5);
        exit(-2);
    }
    return 0;
}

这个代码创建了一个子进程,

而子进程刚运行几秒就结束了,

父进程一直运行也没有回收动作,

下面是运行结果:

image-20230111004825605


特殊的孤儿进程

存不存在这样一种情况;

父进程因为某些愿意突然退出了,

而子进程好好的一直在运行呢?

对上面的代码简单改变一下很容易实现:

int main()
{
    int id = fork();
    if (id > 0)  //父进程
    {
        sleep(5);
        exit(-2);
    }
    else if (id < 0)  //进程创建失败
    {
        perror("fork");
        exit(-1);
    }
    else  //子进程
    {
		while (1);
    }
    return 0;
}

进程刚运行5秒父进程就噶了,

而子进程好好地一直在运行,

此时会发生什么呢:

image-20230111005806586

父进程的父进程是命令行bash,

bash会在父进程结束的时候读取结束信息并回收它。

此时子进程就变成了孤儿进程,仍然在运行,

但子进程的PPID变成了1,

1进程是谁呢?

image-20230111005954829

其实就是操作系统。

此时孤儿进程就被操作系统领养了。

加点打印信息,可以观察到子进程结束时会被操作系统回收:

image-20230111010503228


进程优先级

Linux一个多用户、多任务的操作系统,

系统中通常运行着非常多的进程。

哪些进程先运行,哪些进程后运行,

就由进程优先级来控制。

查看进程优先级可以用下面一条指令;

ps -al | grep name

image-20230111144338236

图中标注的就是进程优先级相关的两个参数,

分别是PRI(priority)NI(nice)

当然这是Linux下的进程优先级表示方法,

并不具有普适性。

PRI还是比较好理解的,即进程的优先级,

或者通俗点说就是程序被CPU执行的先后顺序,

此值越小进程的优先级别越高。

那NI呢?

这就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值。

什么意思呢?

可以用一个简单的公式来解释:

PRI(new) = PRI(old) + nice

这样,当nice值为负值的时候,

该程序将会优先级值将变小,即其优先级会变高,

则其越快被执行。

nice其取值范围是-20至19,一共40个级别

需要强调一点的是,

进程的nice值不是进程的优先级

它们不是一个概念,

但是进程nice值会影响到进程的优先级变化。

可以理解nice值是进程优先级的修正数据

我们可以用top命令更改进程的nice值:

进入top后按"r" –> 输入进程PID –> 输入nice值 -> 按"q"退出:

进程状态3

可以看到将子进程的nice值修改为10之后它的PRI值就变成了90。

此时再变一下:

进程状态4

我们又将子进程的nice值修改为了-10,

但是子进程的PRI并没有变成90-10=80,

而是变成了80-10=70,

不难看出上面那个简单公式中的PRI(old)很多时候固定就是80

另外,我们可以试试将nice值修改至超出其范围看看它是不是真有取值范围:

进程状态5


进程性质补充

竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。

独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。很简单的一个例子,我的微信长时间未响应,但不影响QQ的运行。

并行: 多个进程在多个CPU下分别同时进行运行,这称之为并行。

并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。我们的笔记本都是单CPU,所以我们打开进程管理器这么多运行的进程基本都是并发。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt+C++窗体界面中英文多语言切换

程序示例精选 QtC窗体界面中英文语言切换 如需安装运行环境或远程调试&#xff0c;见文章底部个人微信名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<QtC窗体界面中英文语言切换>>编写代码&#xff0c;代码整洁&#xff0c;规则&#x…

【Linux】软件包管理器 yum

目录 一、什么是软件包 二、如何进行软件安装 1、yum 的使用 2、yum 配置 一、什么是软件包 在Linux下安装软件&#xff0c;一个通常的办法是下载到程序的源代码&#xff0c;并进行编译&#xff0c;得到可执行程序。但是这样太麻烦了&#xff0c;于是有些人把一些常用的软…

InnoDB数据存储结构

InnoDB数据存储结构 本专栏学习内容来自尚硅谷宋红康老师的视频 有兴趣的小伙伴可以点击视频地址观看 1. 数据库的存储结构&#xff1a;页 索引结构给我们提供了高效的索引方式&#xff0c;不过索引信息以及数据记录都是保存在文件上的&#xff0c;确切来说是存储在页结构中。…

不讨论颜色的前提下,如何证明自己不是色盲?神奇的零知识证明

0x01 一个小故事 《阿里巴巴与四十大盗》中有这样一段小故事&#xff1a; 阿里巴巴会芝麻开门的咒语&#xff0c;强盗向他拷问打开山洞石门的咒语&#xff0c;他不想让人听到咒语&#xff0c;又要向强盗证明他知道这个咒语。 那应该怎么办呢&#xff1f; 便对强盗说&#xf…

基于KVM安装部署RHCOS操作系统

参考&#xff1a;Openshift 4.4 静态 IP 离线安装系列&#xff1a;初始安装 - 米开朗基杨 - 博客园 一、Openshift OCP集群安装架构示意图 RHCOS 的默认用户是 core 如果安装有问题会进入 emergency shell&#xff0c;检查网络、域名解析是否正常&#xff0c;如果正常一般是以…

重修JAVA

程序员的差距是在构思上&#xff1a;思想决定了深度&#xff0c;思想的精髓高深是很多人学不来的&#xff01; 每一门语言都有它的特点&#xff0c;有优势也有劣势&#xff0c; 所以不必拘泥于招式&#xff0c;掌握底层原理即可&#xff01; 每一们语言实际上都是一个“工具”&…

如何在您的香港主机帐户上注册多个域名

注册多个域名非常普遍。事实上&#xff0c;香港主机服务提供商鼓励这样做&#xff0c;因为它既有意义又是必要的。下面将介绍决定为什么您可能需要在香港主机上注册多个域名的几个因素。注册多个域名的原因是什么?方便多个项目如果香港主机帐户的所有者在网络上有多个不同域名…

优化vue项目后, 启动编译项目过程中 报 javaScript heap out of memory 错误 及 nodejs内存溢出

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 1、优化vue项目后&#xff0c;运行npm run serve 启动编译项目过程中 报 javaScript heap out of memory 错误 2、项目启动时&#xff0c;出现 nodejs 内存溢出错误 问题描述 提示&#xff1a;遇到…

分布式事务的背景和解决方案

在常用的关系型数据库&#xff0c;都是具备事务特性的。 那什么是事务呢&#xff1f;事务是数据库运行的一个逻辑工作单元&#xff0c;在这个工作单元内的一系列SQL命令具有原子性操作的特点&#xff0c;也就是说这一系列SQL指令要么全部执行成功&#xff0c;要么全部回滚不执…

经典算法之深度优先搜索(DFS)

&#x1f451;专栏内容&#xff1a;算法学习笔记⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;日拱一卒&#xff0c;功不唐捐。 目录一、前言二、基本概念1.简单介绍2. 官方概念三、动图分析四、模板框架五、例题分析组合问题题干描述&#xff1a;思路…

leetcode146. LRU 缓存【python3哈希表+双向链表】利用OrderedDict以及自实现双向链表

题目&#xff1a; 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。实现LRUCache类&#xff1a; LRUCache(int capacity) 以正整数作为容量capacity初始化 LRU 缓存int get(int key) 如果关键字key存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则…

【论文速递】9位院士Science88页长文:人工智能的进展、挑战与未来

【论文速递】9位院士Science88页长文&#xff1a;人工智能的进展、挑战与未来 【论文原文】&#xff1a;Intelligent Computing: The Latest Advances, Challenges and Future 获取地址&#xff1a;https://spj.science.org/doi/10.34133/icomputing.0006摘要&#xff1a; ​…

【阶段三】Python机器学习15篇:机器学习项目实战:支持向量机回归模型

本篇的思维导图: 项目实战(支持向量机回归模型) 项目背景 股票投资(Stock Investment)是指企业或个人用积累起来的货币购买股票,借以获得收益的行为。股票投资的收益是由“收入收益”和“资本利得”两部分构成的。收入收益是指股票投资者以股东身份,按照持股的份…

大网规划部署刷题讲解(带答案)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.大网规划刷题 前言 本章将会讲解大网规划刷题的讲解。 一.大网规划刷题 …

ArcGIS基础实验操作100例--实验85创建线要素间的最近垂线

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验85 创建线要素间的最近垂线 目录 一、实验背景 二、实验数据 三、实验步骤 &#xf…

【一文速通】数据分布不同解决办法

1. 构造合适的验证集当出现训练集和测试集分布不一致的&#xff0c;我们可以试图去构建跟测试集分布近似相同的验证集&#xff0c;保证线下验证跟线上测试分数不会抖动&#xff0c;这样我们就能得到稳定的benchmark。Qiuyan918在基于对抗验证的基础上&#xff0c;提出了三种构造…

为什么流媒体直播的延迟很高

通信技术的发展促进了视频点播和直播业务的兴起&#xff0c;4G 和 5G 网络技术的进步也使得流媒体技术变得越来越重要&#xff0c;但是网络技术并不能解决流媒体直播的高延迟问题&#xff0c;本文不会介绍网络对直播业务的影响&#xff0c;而是会分析直播中常见的现象 — 主播和…

Spring(1):拦截器

1 拦截器 拦截器是Spring中的概念&#xff0c;和过滤器类似&#xff0c;可以对用户请求进行拦截过滤处理。但是相对于过滤器而言&#xff0c;拦截器要的控制更加的细节&#xff0c;拦截器可以在三个地方进行执行&#xff1a; 可以在请求达到Controller控制器之前&#xff0c;…

VirtualBox 客户机/虚拟机无法时间同步?可能是你安装客户机插件的方式不对!

文章目录安装客户机插件的正确方式准备工作安装过程用户手册中的“客户机插件”安装客户机插件的正确方式 准备工作 所需包如下&#xff1a; GNU compiler (GCC)GNU Make (make)Kernel header fileslib* files 笔者亲测使用的 CentOS 7 Linux 内核版本为 3.10.0-1160.81.1.…

SQL索引概念(详解B+树)

SQL索引定义分类复合索引特性复合索引最左特性&#xff08;原则&#xff09;原理索引及其扫描类型索引的优缺点优点:缺点:索引工作原理BTree索引怎么判断是否创建索引&#xff1f;为什么Mysql用B树做索引而不用B-树或红黑树为什么索引快&#xff1f;定义 索引是一种排好序的快…