【Linux进程(二)】操作系统&Linux的进程状态深入剖析

🎬 个人主页:HABuo

📖 个人专栏:《C++系列》 《Linux系列》《数据结构》《C语言系列》《Python系列》《YOLO系列》

⛰️ 如果再也不能见到你,祝你早安,午安,晚安


目录

📚一、一般操作系统层面的进程状态

[📖1.1 运行状态](#📖1.1 运行状态)

[📖1.2 阻塞状态](#📖1.2 阻塞状态)

[📖1.3 挂起状态](#📖1.3 挂起状态)

📚二、Linux下的进程状态

[📖2.1 R状态与S状态](#📖2.1 R状态与S状态)

[📖2.2 D状态与t状态](#📖2.2 D状态与t状态)

[📖2.3 前台进程与后台进程](#📖2.3 前台进程与后台进程)

📚三、总结


前言

上篇博客我们详细地了解了进程,并通过一些简单的指令见了进程,当时相信你会看到其中有一个STAT标识,什么S+、R+等等,这是什么呢?今天我们就来认识认识它:进程状态

本章重点:

本篇文章着重讲究操作系统中的三种进程状态 :运行状态,阻塞状态挂起状态并且讲解Linux操作系统中具体的进程状态,其中R状态(运行状态)和S状态(睡眠状态)最常见,还有一些其它状态,让我们一起认识认识它!


📚一、一般操作系统层面的进程状态

📖1.1 运行状态

现在我们使用的电脑,手机有四核的有八核,十二核的,也就是有多个CPU然而不管有多少个CPU,每一个CPU 都有一个对应的运行队列CPU会去此队列中寻找数据来做处理,一个CPU同一时间内只能运行一个进程,诶?不对啊,那我的电脑是单CPU的那为什么我即登着QQ、又打着CF、又和女友开着微信语音。难道它们不是进程?稍安勿躁,对于这一部分的原因我将在下一篇博客进行解释,先记住,一个CPU同一时间内只能运行一个进程

我们知道了一个CPU同一时间内只能运行一个进程,那么CPU是很快的,运行一个进程我们就去内存拿一个进程是不是有点悲催,虽然前面我们说了内存,也是很快,但是那是相对于硬件来说的,对于CPU你还是太慢了,CPU说这不行,为了提升效率,我必须多拿几个,但是我一个时间又只能运行一个,因此就有了运行队列的概念,就像食堂打饭,窗口每次只能提供一个学生打饭,难道我打完一个,去教室叫一个?显然不合理,所以你要在窗口排队!

因此处于运行队列的进程都是运行状态,注意,进入运行队列中的是我们进程的PCB不是程序数据 ,由此我们又得出一个结论,处于运行状态的进程一定是在运行吗?显然不是,处于运行状态只能说明你在运行队列,啥时候运行要看CPU

整理一下:

  • 一个CPU只有一个运行队列
  • 进入运行队列中的是进程的PCB
  • 处于运行队列的进程就是运行状态
  • 处于运行状态不一定就是处在运行,因为CPU同一个时间内只能运行一个进程

📖1.2 阻塞状态

上面我们看到进程在运行队列里会等待CPU,那么进程会不会等待其它的东西,聪明的你一定会想到我们在写C语言、C++时会有scanf、cin等语句,是不是在等待我们在键盘输入东西,没错,那么聪明的你又会想到,女友1在微信给你发消息、女友2在QQ给你发消息,那么微信、QQ都在等待着键盘输入信息,如果大量的进程同时都需要一个硬件的回馈,那么硬件那么磨蹭能反应的过来吗?所以聪明的硬件像聪明的你一样,借鉴了CPU的那种做法!具体看下:

我们知道系统中的硬件是通过管理硬件数据来间接被操作系统管理起来的,所以操作系统是很清楚硬件现在是否具备访问条件,那么操作系统是怎样知道的呢?其实每一个设备的结构体中,都有变量:PCB* wait_queue,也就是等待队列,请看下图仔细分析:

所以什么叫做阻塞,当一个CPU执行一个进程的时候,运行到需要访问外设时,进程就会被操作系统放到对应的外设的等待队列中,而此时的状态就会变为阻塞状态。当对应的外设准备好之后,进程的PCB将会重新的被放置在CPU的运行队列中,运行该进程的时候,外设就可以访问了

每个CPU或是设备都有自己的队列进程状态变化的本质就是**:**

  • 更改PCB中status的整数变量
  • 将PCB链接到不同的队列中!

📖1.3 挂起状态

挂起状态是一个和阻塞状态容易混淆的概念,我们设想这样一个场景,一个进程在等外设的时候,等待了相当漫长的时间,但是此时,内存又告急,在此存亡危急时刻,操作系统却看到,这个等待外设的进程的程序却翘着二郎腿,在内存里嗑瓜子,你说操作系统会让它悠哉游哉的嗑瓜子?操作系统心想,我都快活不下去了,你还在这嗑瓜子?滚出去!

确实,该进程的程序滚出了内存,但是当他的PCB回到CPU队列的时候,却发现,我的程序不在了,我还怎么运行,这个锅谁背?进程说我在正常运行,不是我的锅,矛头直指硬件,硬件心塞,我本来就慢,你要是嫌我慢就别访问我,这也确实难为硬件了,所以硬件不背,二者回头看向操作系统,操作系统:?,原来是冲我来的,好,老板歇逼了,谁都别干了,难道让老板背锅?所以操作系统也不背。好了婆说婆有理,谁也不背?怎么搞?因此挂起状态扛着九齿钉耙屁颠屁颠的走了过来!

因此挂起状态是:此时进程处于阻塞``状态,并且内存已严重不足,所以``OS会将PCB对应的数据和代码``弄到磁盘,为内存腾出一部分空间此时,进程就被挂起了!挂起并不等同于程序文件不再被拿到内存,而是暂存到磁盘当中,待到秋来九月八,我花开后百花杀,等轮到我的时候,谁都别阻挡我,我必须要拿到内存!

注意,swap分区是磁盘中真实存在的它的大小往往是很小的,这个部分专门 用于内存严重不足时和内存进行交互 并且当内存情况缓解后,曾经被置换出去的代码和数据又会重新加载进来!

📚二、Linux下的进程状态

先来看看Linux库中进程状态的定义:

📖2.1 R状态与S状态

R状态:与一般操作系统普遍概念一致,即处在运行队列中的进程就是运行状态。

S状态:该状态是阻塞状态的一种,它是一种浅度睡眠状态,可以被终止,一般是在等待某种资源时所处的状态。

示例:

cpp 复制代码
#include <stdio.h>    
#include <unistd.h>    
int main()    
{    
    while(1)    
    {    
        sleep(1);    
        printf("我是一个进程\n");    
    }                                                                                                                                                                   
    return 0;    
}  

按照常理来说,一个正在运行的程序应该是处于R状态的,但是这个程序为什么处于S状态呢(+号先不管,后面会讲)

这是因为循环打印时,IO输出是很慢的打印字符会和外设屏幕交互,所以大部分时间进程都处于阻塞状态,可能只有百分之1的时间在打印,所以查看进程状态时,大部分都是S状态,只有很少一部分是R状态**但是如果while(1)中``什么代码都没有,则程序一直处于R状态**

相信你在了解了上述知识点之后,对于这个现象是很容易理解的。

📖2.2 D状态与t状态

对于T/t状态没什么可说就是进程被暂停了嘛,其中库中将t也写成T了,其实t状态是一种可以被追踪的状态,也就是说我们在gdb调试的时候,此时进程的状态就是一种t状态,也是阻塞的一种。

我们重点来讲D状态(一种深度睡眠状态)

假设我们从QQ,微信上将一个文件下载到本地,本质上就是将数据拷贝至磁盘,但是目前这个文件很大,需要拷贝很久,但是此时操作系统的内存恰恰不足了需要干掉一些进程来保证操作系统存活,此时若恰好将正在拷贝到磁盘的进程杀掉了,那么也就是拷贝失败了,如果文件非常的重要,那么操作系统就要背锅了,所以OS创造了D状态:磁盘休眠状态!

所以什么叫做D状态?D状态就是我们进程在长时间等待I/O操作(如磁盘读写),为了防止程序文件以某种原因被操作系统杀掉,将此进程状态设为D状态。 这种状态下的进程正在等待某些资源(通常是I/O资源),并且在这种状态下,进程不会响应任何信号,包括kill -9。这是因为内核认为进程正在进行的操作是至关重要的,不能被中断,否则可能导致数据不一致或系统不稳定。

D状态的特点:

  1. 不可中断 :进程在等待I/O操作(如磁盘读写)完成时进入D状态,此时进程不会响应任何信号,甚至SIGKILL信号也无法杀死它。这是为了防止在I/O操作进行中中断进程,导致数据损坏或系统错误。

  2. 通常由I/O等待引起:当进程需要从磁盘或其他慢速设备读取或写入数据时,由于I/O操作的速度远低于CPU,进程可能会进入D状态,直到I/O操作完成。

  3. 系统资源占用 :处于D状态的进程仍然占用系统资源,如内存,但不会占用CPU时间。然而,如果大量进程长时间处于D状态,可能会导致系统响应缓慢,甚至出现假死现象。

如果一个服务器系统中存在了大量的D状态进程,那这台服务器逼近崩溃的边缘,解决的办法只能是慢慢等它缓过来,如果直接重启,有可能导致大量的数据丢失!

📖2.3 前台进程与后台进程

前面我们看到了某些进程状态后面有+,有的没有,下面我们来介绍它:

  • 前台进程:运行时无法使用bash外壳的指令并且可以被CTRL C强制终止掉(带+)

  • 后台进程:运行时可输入指令,不能被CTRL C掉只能使用kill指令来杀掉进程.(不带+)

将程序变成后台程序:

运行进程时加上: &

如: ./mybin &


📚三、总结

本篇博客我们了解学习了进程的状态,一般操作系统层面的进程状态:运行、阻塞、挂起,对于Linux下的进程状态在了解上述情况下,顺水推舟自然而然也就理解具体操作系统下的进程状态。

小结一下:

一般操作系统层面:

  • 运行:处于运行队列中的状态就是运行状态。
  • 阻塞:进程在运行时,要访问某种外设资源而导致的一种状态。
  • 挂起:进程在阻塞状态下,由于内存紧急,操作系统暂时性的将进程的程序数据放置在磁盘,此时进程所处的状态即为挂起状态。

Linux层面:

  • R:一般操作系统层面的运行状态。
  • S:阻塞状态的一种。
  • D:阻塞状态的一种,相较于S状态,该状态不可被杀掉。
  • t/T:暂停状态,其中t状态可以被追踪(调试过程中可以看到),可以暂停也当然可以继续运行。
相关推荐
yuanmenghao14 小时前
自动驾驶中间件iceoryx - 内存与 Chunk 管理(一)
c++·vscode·算法·链表·中间件·自动驾驶·柔性数组
艾莉丝努力练剑14 小时前
【QT】初识QT:背景介绍
java·运维·数据库·人工智能·qt·安全·gui
石像鬼₧魂石14 小时前
ettercap 命令执行输出的详细解读
linux·学习
曾浩轩14 小时前
跟着江协科技学STM32之4-2OLED显示屏
c语言·stm32·单片机·嵌入式硬件·学习
橘颂TA14 小时前
【剑斩OFFER】算法的暴力美学——面试题 01.02 :判定是否互为字符串重排
c++·算法·leetcode·职场和发展·结构与算法
oMcLin14 小时前
如何在 Ubuntu 22.04 服务器上搭建并优化 Elasticsearch 集群,支持实时日志分析
服务器·ubuntu·elasticsearch
糯诺诺米团14 小时前
C++多线程打包成so给JAVA后端(Ubuntu)<2>
java·开发语言·c++
-西门吹雪14 小时前
c++线程之再研究研究多线程
开发语言·c++
阿巴~阿巴~14 小时前
TCP可靠传输双引擎:确认应答与超时重传的精妙协同
运维·服务器·网络·网络协议·tcp·超时重传·确认应答