Linux:理解进程的多种状态

news2025/2/23 2:25:28

文章目录

  • 理解状态
  • 运行状态
  • 阻塞状态
  • 挂起状态
  • Linux系统下的进程
    • 状态的解析
    • 状态的查看

本篇总结的是进程的多种状态

对于进程的状态理解,在教材上通常是有下面的思维模式图

在这里插入图片描述
那么如何理解上面图片中的内容?

理解状态

如何理解状态?其实理解状态很简单,状态就是PCB中的一个变量,例如说在PCB中,可能会有一个变量定义为 int status,而在代码外面定义

#define NEW 1
#define RUNNING 2
#define BLOCK 3

由此可以可以借助上面的宏定义,将状态进行修改

pcb->status=NEW;
...

因此,所谓状态的变化过程,实际上就是修改整形变量的过程,通过修改整形变量就可以实现修改状态,那这个状态表示有什么用?

if(pcb->status == NEW)
{
	// PCB进入运行队列
	...
}
else if(pcb->status == BLOCK)
{
	// PCB进入阻塞队列
	...
}

进程的状态,其实就是PCB的一个变量,因此状态只和PCB有关系,和代码数据无关

运行状态

运行状态是进程多种状态中的一种,那如何理解运行状态?

只要在运行队列中的进程,状态都是运行状态

上面是对于运行状态的定义,但是又引入了新的概念,什么是运行队列呢?

通常来说,一个CPU可以负责管理一个运行队列,这里默认设备是一个单核的设备,那么CPU和内存和操作系统的管理方式如下所示:

在这里插入图片描述
每个CPU在系统层面上都会维护一个运行队列

对于上图来说,CPU就进行维护了一个runqueue队列,这个队列管理了一串PCB,而这当中的每一个PCB又进行管理了它们对应的可执行程序,此时,每一个可执行程序对应的PCB中的status数据都是NEW,代表着这些程序是正处于运行状态,是可以被随时调度的,因此上面这些概念再结合上图其实就是运行状态的概念

阻塞状态

总结了运行状态,就要进行阻塞状态的学习,那什么是阻塞状态?

以下面的例子为例:

#include <stdio.h>

int main()
{
	int a;
	scanf("%d",&a);
	printf("%d",a);
	return 0;
}

这是一个很简单的程序,输入一个值,再将这个值输出,当开始运行的时候这个程序就进入了内存中,操作系统为它生成了PCB进行管理它,此时它就变成了一个进程,但是如果一直不输入值,换句话说,键盘上面的数据没有就绪,因此进程要访问的资源没有就绪,此时进程的代码就不能向后执行,这样就被称之为阻塞状态

操作系统作为管理的软件,自然是会在第一时间知道这件事的,它马上知道这个进程不能正常进行了,被阻塞了,因此就把状态修改为BLOCK,但这并没有结束,操作系统在修改状态的同时就要将这个进程移除运行队列,那移动到哪里?答案是等待队列

那又引入了一个新词,什么是等待队列?这就要回到前面的问题,阻塞状态是如何产生的?

在我们写的代码中,一定会有一些代码是需要访问系统的资源的,比如说最简单的输入输出需要用到键盘和显示器,甚至有些代码还可能用到磁盘网卡等各种硬件的设备,换种角度来讲,从本质来看,是用户想要从这些硬件中获取到用户想要的信息,但是现在用户不输入,键盘的数据没有准备就绪,那么进程需要从scanf中得到的数据就没有就绪,因此就不具备访问的条件,进程的代码不能正常进行,而此时操作系统是知道这件事的,因为在操作系统的底层逻辑中它是可以管理到整个软硬件资源的,因此针对这种硬件设备异常的问题,操作系统也有自己的解决方法

操作系统会将它所管理的硬件设备也进行描述,对硬件设备构建属于它们自己的结构体,因此有了下面的演示:

在这里插入图片描述
操作系统会对它所管理的硬件设备也创建它的描述,这里叫为dev,在这个结构体中也会描述一系列状态,比如说类型,对应到底是什么设备,比如状态,对应现在硬件的情况是什么,比如指针,可以将数据连起来可以进行链式访问,还有下面要提到的wait_queue

前面提到,当一个运行状态的进程被判定为现在是阻塞状态时,它就已经不能再在运行队列中了,那么它应该去哪里呢?这就引出了等待队列的概念,当进程进入阻塞状态的时候,它就会被放到等待队列中进行等待

在这里插入图片描述
而当阻塞队列中的进程的状态回到运行状态了,就可以将阻塞队列的进程再拿回到运行队列中即可

因此,进程状态变化的本质?

  1. 更改PCBstatus的变量
  2. PCB连入不同的队列中

而由此可以得出一个结论:在操作系统中,会存在非常多的队列,运行队列,等待硬件的设备等待队列等,所有系统内的进程都是用双链表链接起来的

挂起状态

什么是挂起?

前面明确一个概念,如果进程处于阻塞状态,那么就说明,此时此刻它所等待的资源在没有就绪的时候,这个进程是不能被调度的,但这个进程现在依旧处于内存中,如果数量比较少不会造成什么影响,如果数量到达一定程度以至于操作系统内的资源已经严重不足得时候,这时会怎么办?

在这里插入图片描述
对于这种情况,操作系统的选择是,将内存数据置换到外设,这个操作是针对所有的阻塞进程的,如下图所示:

在这里插入图片描述
交换的位置在哪里?操作系统将信息转移到了swap分区内,当进程被操作系统调度的时候,被加载到这些分区的代码和数据就会被重新加载进来,也就是说,这是一个换入和换出的过程,而将信息交换到磁盘上后进程的状态,就被称之为挂起状态

弊端在于哪里?

这样的行为一定是有弊端的,由于牵扯到数据的输入和输出的过程,这个过程一定会导致效率降低,但是这是操作系统为了保证整个系统的良好运行而做出的选择,如果不做出这个选择那么整个系统都有挂掉的风险,因此在实际的开发中,swap分区的大小通常设置和内存的大小一样即可

Linux系统下的进程

本篇在总结操作系统的概念中,大多数情况下是根据的是Linux下的系统,那么就需要具体的进入操作系统的源代码中去寻找具体的信息:

Linux中进程的状态表示

/*
 * 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 *task_state_array[] = {
	"R (running)",		/*  0 */
	"S (sleeping)",		/*  1 */
	"D (disk sleep)",	/*  2 */
	"T (stopped)",		/*  4 */
	"T (tracing stop)",	/*  8 */
	"Z (zombie)",		/* 16 */
	"X (dead)"		/* 32 */
};

从上面的学习中知道,进程有运行状态,阻塞状态和挂起状态,那么落实到Linux内核源码中,它的实现也是要根据这个原理进行设计

例如在上面的源码中看到,有running状态,也有sleepingdisk sleep状态,也有stoppedtracing stop状态,也有zombiedie状态,下面就对这些状态进行分析:

状态的解析

  1. R运行状态:表示的是进程在运行中或者是在运行队列中,也不一定是一定表示为在运行中
  2. S睡眠状态:表示的是进程正在等待一个事件的完成
  3. D磁盘休眠状态:表示的是不可中断睡眠状态,后面进行详解
  4. T停止状态:表示进程被停止了,可以通过信号重新启动等等
  5. X死亡状态:表示进程被杀死了

状态的查看

对于状态的查看可以使用定时脚本来实时监测状态,以及使用ps指令来进行监视状态

首先写一个C程序死循环,这样可以实时监测到运行状态

#include <stdio.h>
#include <unistd.h>

int main()
{
    while(1);
    return 0;
}
# 运行程序
[test@VM-16-11-centos process]$ vim process.c
[test@VM-16-11-centos process]$ make
gcc -o process process.c
[test@VM-16-11-centos process]$ ./process

# 使用脚本观察进程状态
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
  365  2397  2397   365 pts/0     2397 R+    1003   0:05 ./process

此时对于状态一栏显示的是R+,那么加号代表什么意思?

Linux中的进程也分为很多种,比如说有前台进程和后台进程,那么带加号的进程就被称为前台进程,前台进程和后台进程最明显的一个区别是,不能输入指令供bash来解释

Linux中,可以使用&

在这里插入图片描述
但对应的问题是使用Ctrl+C不可以终止程序,需要用kill命令来终止进程

休眠状态

Linux中还存在休眠状态的进程,其实也就对应着阻塞状态的进程,在这个状态下的进程是不会被运行的,而休眠状态也有两种,浅度睡眠和深度睡眠

浅度睡眠

以前面举的例子为例,当现在运行的程序需要输入一个值的时候,此时如果用户一直不输入值,那么程序就会从运行队列踢出,在等待队列进行等待,此时程序就处于阻塞状态,但如果此时Linux系统的运行压力过大,它是可以通过杀掉进程来节省资源的

杀掉进程的代价是很大的,如果进程只是一些运行的程序还不算很大损失,但如果是向磁盘写入信息?对于这个进程来说,如果被杀掉了进程,那么对于用户来说是很大的损失

深度睡眠

因此为了避免这样的情况出现,Linux系统刻意创建了一个disk sleep状态,它被叫做磁盘睡眠状态,是专门为了磁盘来设计的,也叫做深度睡眠状态,对于进入深度睡眠状态的进程来说,它是不会被随意终止的,操作系统也没有权力对这种状态的进程做操作,这样做的目的就是为了保护和磁盘进行数据交互的进程被操作系统意外终止

终止

Linux中存在一个状态是Tt状态,现在几乎对这两个系统不做太多区分,这两个状态都是对进程进行暂停,tracing stop更指向的是对进程进行追踪,例如在debug模式下追踪断点的这个过程

为什么?

由于在进行软件资源访问的时候,可能会需要暂时对进程停止访问,就将进程设置为STOP即可

实际运用?

Linux的调试工具gdb中,有一个操作叫做打断点,而打断点的实质就是在debug程序的时候,可以追踪程序,如果遇到断点,进程就停止了,也就是说调试程序实际上就是进程在运行,而打断点停下来的过程实际上就是进程被终止的过程

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

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

相关文章

什么是HTTP头部(HTTP headers)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 理解 HTTP 头部&#xff08;HTTP Headers&#xff09;⭐ HTTP 头部的分类⭐ HTTP 头部的应用⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#x…

基于Python Django的公务员考试信息管理系统

文章目录 1 简介2. 技术栈3 功能分析4 功能具体设计4.1 软件功能模块设计4.2数据库设计与实现4.2.1概念模型设计4.2.2数据库逻辑结构设计 5系统详细设计5.1系统功能模块5.2管理员功能模块 六 源码咨询 1 简介 公务员考试信息管理系统的开发运用Python技术&#xff0c;MIS的总体…

8月数据出炉!NOA与激光雷达「分道扬镳」?降本大战升级

对于激光雷达赛道来说&#xff0c;如何在市场整体需求更加偏向强调性价比的背景下&#xff0c;继续维持前装出货的增速&#xff0c;已经成为新的考验。 进入2023年&#xff0c;高阶智驾&#xff08;中国市场以NOA为代表&#xff09;&#xff0c;继续保持向上势头。8月&#xff…

Archlinux Timeshift的系统备份与还原

服务器在滚挂或误删系统文件,timeshift系统备份与还原的情景: 安装 timeshif 1 yay -s timeshif 备份设置 选择快照类型 此处选择【RSYNC】 选择储存位置 每台设备安装分区不一样,大家安装实际情况选择,一般选择比较大的空间存储,并且最好是机械,这样不容易损坏 设置计…

实战项目:VB实现小鸟快跑小游戏

文章目录&#xff1a; 一&#xff1a;效果演示 二&#xff1a;实现思路 三&#xff1a;代码实现 form1 效果图 代码 form2 效果图 代码 一&#xff1a;效果演示 效果图◕‿◕✌✌✌ 代码下载 二&#xff1a;实现思路 窗口1 就是实现窗口的跳转和关闭窗口2 1.先添加背…

【接口测试】Chrome浏览器F12调试工具抓包详细分析(超细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 调试时使用最多的…

Docker网络+资源控制

一、Docker网络 Docker 网络实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c;Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Container-IP&#xff0c;同时Docker网桥是每个容器的默认网关。…

【计算机网络】IP数据报首部格式、最大传输单元MTU、最大分段大小MSS

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多计算机网络知识专栏&#xff1a;计算机网络&#x1f525; 给大家跳段…

【生育险报销】

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

计算机视觉与深度学习-图像分割-视觉识别任务03-实例分割-【北邮鲁鹏】

目录 参考定义Mark R-CNN结构思路Mask R-CNN训练阶段使用的Mask样例Mask R-CNN实例分割结果Mask R-CNN检测姿态 参考 论文题目&#xff1a;Mask R-CNN 论文链接&#xff1a;论文下载 论文代码&#xff1a;Facebook代码链接&#xff1b;Tensorflow版本代码链接&#xff1b; K…

51单片机3【单片机的种类】

1.51单片机发展史 1. 发展史 &#xff08;1&#xff09;总结&#xff1a;早期是不分单片机和其他CPU的&#xff0c;早期都是一起的&#xff0c;后来应用级别的高端CPU相继推出用于别的行业&#xff08;PC&#xff0c;手机&#xff09;其中一支专用与低性能&#xff0c;低价格作…

Java基础简单整理

文章目录 Java语言具有以下特点&#xff1a;Java SE vs Java EEJVM vs JDK vs JRE为什么说 Java 语言编译与解释并存&#xff1f;Java 和 C 的区别?Java注释用法&#xff1a;Java标识符Java基本数据类型链接Java字符串类型链接基本类型和包装类型的区别&#xff1f;静态方法为…

Unity实现设计模式——观察者模式

Unity实现设计模式——观察者模式 观察者设计模式定义了对象间的一种一对多的组合关系&#xff0c;以便一个对象的状态发生变化时&#xff0c;所有依赖于它的对象都得到通知并自动刷新。 简单来说就是某个人需要收到通知只需要订阅这个通知&#xff0c;当通知发送时会发送到每…

自定义热加载:如何不停机实现核心代码更新

文章目录 1. 常见的几种实现代码热更新的几种方式对于开发环境我们可以使用部署环境1. 使用 Arthas 的 redefine 命令来加载新的 class 文件2. 利用 URLClassLoader 动态加载3. 通过Java的Instrumentation API 也是可以实现的 2. 实现1. ClassScanner扫描目录和加载类2. 定时任…

system trace

adb shell stopadb shell start //重启adb 数据会干净点adb shell //也试过在adb shell 外面dump system trace&#xff0c;但是同样的参数dump出来看不到如此详细&#xff0c;比如makeApplication的时长&#xff0c;线程执行被中断等atrace -z -b 40000 am wm view res ss g…

常用接口测试工具

首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能给你…

如何使用ASO优化来提高应用的安装率

应用程序的成功并非一蹴而就&#xff0c;它需要大量的时间和工作&#xff0c;而这一切都取决于对流程的深入理解、对结果的衡量以及对执行的某些营销活动的有效性进行分析。但哪些优化在App Store或Google Play上取得成功最关键&#xff1f;为了取得成功&#xff0c;我们必须跟…

2023/9/27 -- ARM

【汇编语言相关语法】 1.汇编语言的组成部分 1.伪操作&#xff1a;不参与程序的执行&#xff0c;但是用于告诉编译器程序该怎么编译 .text .global .end .if .else .endif .data2.汇编指令 编译器将一条汇编指令编译成一条机器码&#xff0c;在内存里一条指令占4字节内…

服务断路器_Resilience4j重试机制

重试机制比较简单&#xff0c;当服务端处理客户端请求异常时&#xff0c;服务端将会开启重试机制&#xff0c;重试期间内&#xff0c;服务端将每隔一段时间重试业务逻辑处理。 如果最大重试次数内成功处理业务&#xff0c;则停止重试&#xff0c;视为处理成功。如果在最大重试次…

手动关闭Spring定时任务

一、问题 比如我写了一个这样的定时任务类&#xff0c;该定时任务很简单&#xff1a;每秒打印一行craneing… 那么后期我想中途关闭和开启这个定时任务应该怎么处理&#xff1f; 二、解决 spring定时任务依赖 ThreadPoolTaskScheduler 这个类&#xff0c;我们只需要顶掉这个…