【Linux】进程状态的理解
✍作者:阿润菜菜
📖专栏:Liunx系统编程
本文目录
- 概述
- 两个先行概念
- 我们为啥创建进程
- Linux下的进程状态
- 1. R 运行状态
- 2.S 休眠状态 --- 可中断休眠状态
- 3. D 磁盘休眠状态 ---不可中断休眠
- 4.T 暂停状态 (t 追踪暂停状态)
- 5. X 死亡(瞬时)状态
- 6. Z 僵尸进程
概述
引入
其实在我们运行程序时,CPU并不是一个进程一直在运行,而是一个进程跑一会,另一个进程跑一会,这样间替周而复始。----- 分时操作系统
那凭什么要运行这个进程而不是另一个? 答案就取决于 进程状态
我们来看一下在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 * 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 */
};
可以看到状态态在kernel源代码里定义的方式大概是用一个数组包装,用不同的数字来标识不同的状态,如 0 代表R(运行)状态
- R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里
- S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))
- D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
- T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。注意还有个小写t 对应的是追踪暂停状态
- X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态
因为操作系统有很多,每个操作系统对进程的管理都有所差别,但基本原理是一样的,我们下面来研究Linux操作系统来观察进程状态
两个先行概念
阻塞:进程因为等待某种条件就绪,而导致的一种不推进的状态 ---- 进程卡住了 ---- 一定是在等待某种资源 ( 进程等待某种资源就绪的过程)
就比如我写了个scanf代码,当CPU运行到此处时,需要等待我从键盘进行输入,此时进程的状态就是阻塞状态。
为什么程序多会卡? 因为启动了太多的进程,操作系统难以调度过来,进程卡住了(阻塞!)
为什么要有阻塞? 进程要通过等待的方式,等具体的资源被别人用完之后,再被自己使用
挂起:闲置进程的代码和数据被交换到磁盘中(可以看作成一种特殊的阻塞状态)
注:
阻塞就是不被操作系统调度,一定是当前进程需要等待某种资源就绪,一定是task_struct结构体需要在被某种OS管理下的资源下进行排队
我们为啥创建进程
因为我们想要让进程帮我们办事情。进程给我们办事情我们就会关心结果,为了使程序能并发执行,且对并发执行的程序加以描述和控制(PCB),我们引出了进程的概念。
计算机在开机的时候,操作系统就会被加载到内存里面,磁盘中的程序在运行的时候也会被加载到内存里面,实际上是加载到操作系统内部,受操作系统的管理,我们知道程序运行的时候,是需要CPU进行读取进程的代码并计算的,但进程的数量一定会比CPU多,那CPU该怎么一个个的读取进程代码并计算呢?答案是通过运行队列(PCB数据结构)来对进程的运行进行管理。
Linux下的进程状态
我们可以通过测试代码进行观察
1. R 运行状态
1 #include <stdio.h>2 #include <unistd.h>3 #include <sys/types.h>4 5 int main()6 { 7 while(1) 8 {} 9 }
当程序代码只是一个死循环时,我们将程序运行起来,然后查看进程状态,可以很明显的看到状态是R,也就是运行状态。
,并不是CPU内维护。运行队列中是task_struct (PCB控制块)
2.S 休眠状态 — 可中断休眠状态
如果我们在刚刚代码中加入一句printf实现在显示屏上打印再来观察进程状态会出现什么?
结果
我们在代码中添加printf语句之后,程序还在运行,但观察到的进程的状态是S休眠状态,这是为什么呢?
因为我们的代码中访问了外设资源,即显示器。我们知道CPU会飞速的运行完进程的所有代码,但是我们写的进程需要占用硬件资源,每一次占用硬件资源都要等显示器就绪,这会花很长的时间(CPU计算的速度和IO的速度差别大概是几十万倍)。大概率99%的时间是进程在等显示器就绪,也就是在等待IO就绪,1%的时间是CPU在运行进程的代码,所以我们在查看进程状态的时候,极大概率上查到的都是S休眠状态。更形象化的说明就是,在进程访问完毕一次显示器的时候,CPU已经将这个死循环代码执行了50、60万次,所以我们在查看进程状态的时候,进程都是在等IO就绪的,所以就会查看到进程是休眠状态,这也是阻塞状态的一种。
S 休眠状态的两种
S 休眠状态本质是一种阻塞状态
S+: 前台运行 可以ctrl C暂停
S:后台运行 不可以Ctrl C暂停 可以直接kill 干掉
3. D 磁盘休眠状态 —不可中断休眠
S状态是浅度睡眠状态,是可以被终止的,通过ctrl+c或kill -9 pid两种方式进行分别进行前后台终止。
背景
当阻塞进程过多时,操作系统会将一些进程挂起,以此来解决内存空间不足的问题。如果挂起依旧无法解决内存空间不足,Linux操作系统就会将进程杀死,但是这样杀死进程很有可能导致进程对应的IO过程失败,从而丢失大量数据,这会对用户造成巨大的损失,所以就出现了一个新的进程状态,深度睡眠状态,这样的进具有无法被操作系统kill掉的特性。一般情况下,处于D状态的进程,只能等待IO过程结束,让进程自己醒来,重新投入CPU的运行队列,重新继续运行进程。或者万不得已可以通过断电的方式来杀掉深度睡眠的进程!!!
当然深度睡眠的状态一般不会出现,只有高IO的情况下,运行某个程序时,进程才有可能出现深度睡眠的状态。如果处于这种状态,计算机也宕机了。
4.T 暂停状态 (t 追踪暂停状态)
本质是阻塞状态的一种。
我们可以通过kill命令进行进程暂停状态的操作
kill -19 + 进程id --- 停止运行进程
kill -18 + 进程id --- 继续运行进程
注:状态后面带+,表示前台进程,状态后面不带+,表示后台进程
t 追踪暂停状态
Linux内核源代码中为了区分跟踪暂停和暂停状态,将T改为t来表示追踪暂停状态
适用在我们调试断点处 本质:暂停进程
当我们在调试某个二进制程序的时候,其实就是在调试该进程,当进程中有断点的时候,gdb中按下r进行调试运行,此时就会由于断点的存在而停下来,这其实表示的就是我们当前运行的进程停下来了,等待我们查看当前进程的上下文数据,这就是tracing stop状态,跟踪状态。
5. X 死亡(瞬时)状态
当进程结束时会显示X 状态,由于CPU处理的速度之快,我们极难观察到。
6. Z 僵尸进程
想一下如果一个进程退出了,立马进入X状态,你作为父进程,有没有机会拿到退出结果呢?
僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)
没有读取到子进程退出的返回代码时就会产生僵死(尸)进程。
所以Linux当进程退出的时候,一般进程不会立即彻底退出,而是要维持一个状态叫做:Z 僵尸状态。—方便后续父进程(OS)读取该子进程退出的退出结果。
只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。
代码示例:
1 #include <stdio.h>2 #include <unistd.h>3 #include <stdlib.h>4 5 int main()6 {7 8 pid_t id = fork();9 10 if (id==0)11 {12 printf("I am a child process,pid:%d,ppid:%d\n",getpid(),getppid());13 sleep(5);14 exit(1);15 }16 else17 {18 while(1)19 {20 printf("I am a parent process,pid:%d,ppid:%d\n",getpid(),getppid());21 sleep(1); 22 }23 }24 return 0;25 }
结果:
僵尸进程危害
那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
进程的退出状态属于进程的基本信息,也是需要数据进行维护的,所以这种信息会被保存在进程对应的PCB里面,如果进程的状态一直是Z状态的话(父进程一直不读取子进程的退出状态),那么PCB就需要一直维护这种状态信息,虽然子进程对应的代码和数据会被释放,但是PCB是不会被释放的,因为他需要维护进程的Z状态,所以这个时候就会产生内存泄露的问题
僵尸进程无法被杀掉,即使通过kill信号也无法杀掉,因为它已经死亡了,所以无法被杀掉的进程有三个,深度睡眠进程,僵尸进程,死亡进程,D状态是不能杀,Z和X是无法杀,因为已经死了! 😳
在结束进程之后,操作系统拿到退出码,进行甄别帮我们将父进程和子进程一起回收掉。以免内存泄露的发生。
相关文章:

【Linux】进程状态的理解
✍作者:阿润菜菜 📖专栏:Liunx系统编程 本文目录概述两个先行概念我们为啥创建进程Linux下的进程状态1. R 运行状态2.S 休眠状态 --- 可中断休眠状态3. D 磁盘休眠状态 ---不可中断休眠4.T 暂停状态 (t 追踪暂停状态)5…...

打游戏哪种蓝牙耳机比较好?适合玩游戏的无线蓝牙耳机
2023年耳机市场一如既往地卷,不只是卷音质,还在外观和功能上做了许多的改进,以至于现在哪怕不懂耳机的人从各电商平台都能闭眼入一个款平价品牌耳机且极少会踩雷,玩游戏是当前年轻人的娱乐方式,下面整理了几款适合玩游…...

Fortinet推出新一代自研安全芯片,跨所有网络边缘加速网络与安全融合
专注网络与安全融合的全球网络安全领导者 Fortinet(NASDAQ:FTNT),近日宣布推出新一代自研安全芯片 FortiSP5,作为 Fortinet ASIC 技术的最新突破,有力推动了分布式网络边缘安全的重大飞跃。FortiSP5 源自 F…...

ChatGPT爆火背后的真相:学编程已经成为必选项
这一阵最热门的话题,莫过于人工智能新选手——ChatGPT,在推出后只用了两个月就积累了1亿用户!它的出现在科技圈掀起了一阵“惊涛骇浪”,有人称ChatGPT的意义,堪比当年蒸汽机的出现,它足以爆发新一轮的“工业…...

Unity UI框架
一、简介 最近在各大网站看了一下 Unity3d 的 UI 框架,各种 UI 框架已经有很多的版本了,各有千秋,有的功能虽然写的完善,但用起来太复杂,有的框架功能不完善,搞个课程就上架了,还有什么 MVC 框…...

vue2提取vue-router的title单独存放,使用i18n实现
成品效果 首先引入i18n(vue-i18n官网文档) 依赖包 npm install vue-i18n8然后单独在src目录下新建一个文件夹lang,存放相对应的变量名称,我这里只做显示中文所以其他引入我都注释了,具体目录如下: src\lang/zh.js部分代码 export…...
【Linux操作系统】【综合实验三 用户帐号、文件系统与系统安全管理】
文章目录一、实验目的二、实验要求三、实验内容四、实验报告要求一、实验目的 要求掌握Linux系统用户的创建、删除与管理操作;熟悉Linux文件系统的管理模式,学会创建用户文件系统并装载和卸载文件系统;掌握超级用户的管理方式与权限…...
sqlite3数据库-sqlite语句1(五)
DML(Data Manipulation Language,数据操作语言) SELECT:查询表中的数据;SELECT语句中使用WHERE子句SELECT <列名>,... FROM <表名> WHERE <条件表达式>;SELECT id,name,purchase_price FROM Product; /*使用逗号分隔查询多列,顺序同子句顺序*/ SELECT * FROM…...

【图像分类】卷积神经网络之LeNet5网络模型实现MNIST手写数字识别
写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 在上一篇博文中我们对LeNet5网络模型的结构进行了剖析,本篇博文,我们将使用PyTorch搭建LeNet5实现MNIST手写数字…...

前端开发环境搭建
文章目录Node.js是什么安装查看版本入门示例NPM使用 npm 命令安装模块常见命令使用淘宝 NPM 镜像TypeScript安装入门示例从github拉取构建项目如何从零创建一个TypeScript项目规划目录结构新建项目Web App运行服务添加依赖打包使用browserify打包使用webpack打包推荐流程目录配…...
学习Flask之四、网页表单
第二章介绍的request对象,使用了客户端请求的所有信息。特别地,request.form提供了对POST请求提交的表单数据的访问。尽管Flask请求对象的支持足于处理网页单,但是还有很多作务很繁锁和重复。两个很好的例子是产生HTML表单代码和验证表单数据…...

CenterMask paper笔记
CenterMask是一个anchor free的实例分割模型, 来自paper: CenterMask: Real-Time Anchor-Free Instance Segmentation 提起anchor free, 会想到FCOS模型,是用来目标检测的, 那么这里就用到了FCOS, 不过换了backbone, 在FCOS检测出目标框后&…...

06- OpenCV查找图像轮廓 (OpenCV基础) (机器视觉)
知识重点 灰度图转换: gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)二值化: 返回两个东西,一个阈值, 一个是二值化的图: thresh, binary cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)查找轮廓: 返回两个结果,分别是轮廓和层级: c…...

OpenGL学习日记之模型绘制
自己编译运行过程中遇到的一些问题 下载Assimp已编译的lib(因为我们公司的电脑有很多权限和限制,也不能自己安装一些没有报备的软件,所以愁方便我就没有用cMake自己编译了)找到一位免费分享的博主的。 https://blog.csdn.net/lady_killer9/article/deta…...

Springboot接口多个DTO入参的Postman上传方式
在Java中使用Spring Boot框架时,可以同时使用多个DTO作为方法参数。 TO(Data Transfer Object)是一个常见的设计模式,用于封装数据传输对象。它通常用于将数据从一个层传递到另一个层,例如将数据从服务层传递到控制器…...
软考各科目考核内容详细介绍,看这里
新手在准备报考软考时,都会遇到这样的一个问题——科目这么多,我适合考什么?要想知道自己适合报什么科目,就需要了解每个科目是什么,考什么等一系列的问题。 接下来,就为大家介绍一下软考的各个科目&#…...
连续时间信号与离散时间信号
前言 《信号与系统》是一门很难的课,也是许多学校考研要考的专业课,由于每周只有两节课,所以每次上完都要及时的去复习,这里参考的教材是奥本海姆著作,刘海棠译,北京:电子工业出版社࿰…...

TPM密钥管理、使用
前面讲过证书相关内容,除了在软件方面有所应用外,在硬件方面也有很多应用。本次讲一下TPM相关的内容。 一、TPM介绍 1.1背景 TCG基于硬件安全的架构是为应对1990s后期日益增多的复杂恶意软件攻击应用而生的。当时以及现在,抵御PC客户端网络…...

return和finally执行顺序、运行时异常与一般异常异同、error和exception区别、Java异常处理机制原理与应用
文章目录1.try {}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?2.运行时异常与一般异常有何异同?3.java 程序中的错误有三种类型分别是什么4.error和exception有什么…...

我为什么放弃WinUI3
基于WinUI3开发HiNote已经有一个多月的时间了,算是做出来一个简单能用的C端软件。 基于个人的经历,说说其中的开发体验。 UI设计语言 无论是否抄袭苹果,WinUI3给人的感觉都是眼前一亮的。简洁美观,现代化,毛玻璃的美…...
Redux:不可变数据与纯函数的艺术
Redux:不可变数据与纯函数的艺术 状态管理的困境 随着现代 Web 应用功能的不断扩展,前端开发者面临着日益复杂的状态管理挑战。当应用从简单的表单交互发展到复杂的单页应用时,组件间共享状态的问题变得尤为突出。想象一个电商平台…...
矩阵分解相关知识点总结(二)
文章目录 三、矩阵的QR分解3.1、Givens矩阵与Givens变换3.2、Householder矩阵与Householder变换3.3、QR分解 书接上文矩阵分解相关知识点总结(一) 三、矩阵的QR分解 3.1、Givens矩阵与Givens变换 设非零列向量 x ∈ R n \bm{x}\in {\bf{R}}^n x∈Rn及单…...

服务器安装软件失败或缺依赖怎么办?
服务器在安装软件时失败或提示缺少依赖,是运维中非常常见的问题。这个问题大多发生在 Linux 云服务器环境,原因和解决方法也有共性。以下是详细说明和解决建议: 🧠 一、常见原因分析 问题类型描述🔌 软件源不可用服务器…...
人工智能-Chain of Thought Prompting(思维链提示,简称CoT)
Chain of Thought Prompting(思维链提示,简称CoT) 是一种通过引导大模型生成中间推理步骤来增强其复杂问题解决能力的技术。它让模型在回答问题时,不仅输出最终答案,还展示出逐步分解问题、逻辑推理的过程。以下是大模…...
我的创作纪念日——聊聊我想成为一个创作者的动机
2025年6月4日,是我在CSDN写下第一篇技术博客的第1024天。 1024,这个数字对于程序员来说意义非凡,它不仅是内存单位的基础,更是我们这群“码农”的节日符号。而对我来说,它更像是一段旅程的里程碑:从一个曾想…...

《一生一芯》数字实验三:加法器与ALU
1. 实验目标 设计一个能实现如下功能的4位带符号位的 补码 ALU: Table 4 ALU 功能列表 功能选择 功能 操作 000 加法 AB 001 减法 A-B 010 取反 Not A 011 与 A and B 100 或 A or B 101 异或 A xor B 110 比较大小 If A<B then out1…...
rocketmq延迟消息的底层原理浅析
rocketmq延迟消息的底层原理 消息实体 延时消息是指允许消息在指定延迟时间后才被消费者消费 Apache RocketMQ 中,消息的核心实体类是 org.apache.rocketmq.common.message.Message public class Message implements Serializable {private String topic; …...

C++进阶--C++11(04)
文章目录 C进阶--C11(04)lambdalambda表达式语法捕捉列表lambda的应用lambda的原理 包装器functionbind 总结结语 很高兴和大家见面,给生活加点impetus!!开启今天的编程之路!! 今天我们进一步c…...
NodeJS全栈WEB3面试题——P3Web3.js / Ethers.js 使用
3.1 Ethers.js 和 Web3.js 的主要区别是什么? 比较点Ethers.jsWeb3.js体积更轻量,适合前端较大,加载慢,适合 Node文档文档简洁、现代化,支持 TypeScript文档丰富,但不够现代化模块化设计高度模块化&#x…...
macos常见且应该避免被覆盖的系统环境变量(避免用 USERNAME 作为你的自定义变量名)
文章目录 macos避免用 USERNAME 作为你的自定义变量名macos常见且应该避免被覆盖的系统环境变量 macos避免用 USERNAME 作为你的自定义变量名 问题: 你执行了:export USERNAME“admin” 然后执行:echo ${USERNAME} 输出却是:xxx …...