个人主页:Lei宝啊
愿所有美好如期而遇
目录
进程状态介绍
首先,进程状态有运行,阻塞,挂起,这些只是一个大体的概括,具体的状态我们后面会一一说到。
我们知道,task_struct是Linux进程控制块,实际上我们的进程状态值就定义在里面,在进程状态改变的时候,只需要改变它的值即可。
那么进程状态决定了什么呢?他决定了进程的后续动作,是继续执行,还是终止,如果多个进程都已经就绪,都需要执行,但是我们只有一个CPU,不可能同时执行,于是就有了进程排队,
关于进程排队,参考:进程排队https://blog.csdn.net/m0_74824254/article/details/134549038?spm=1001.2014.3001.5501
运行状态:不是只有正在CPU上执行的进程才是运行状态,而是只要在CPU运行队列上的进程就处于运行状态。
阻塞状态:程序在等待某种软硬件资源时,就会从运行队列迁移到等待队列,此时就是阻塞状态。
挂起状态:在计算机资源吃紧,也就是运行内存不够时,为了保证操作系统不会挂掉,以及大部分进程仍然能够继续跑下去,会将一些进程的代码和数据先唤出到磁盘上的swap分区,腾出一部分内存空间。
我们这里只提及阻塞挂起。
在一些进程等待某些硬件资源,但是硬件资源没有就绪,计算机资源此时又非常吃紧,如果不及时清理内存空间,就会崩掉,到时候谁也别想运行,那么此时处于阻塞状态的进程就是非常好的清理对象,占着内存空间,然后还不运行,此时操作系统就会将他唤出到磁盘上的swap分区。
当操作系统顶住了这波压力,内存没那么吃紧的时候,我们这个进程的硬件资源也就绪了,task_struct迁移到了运行队列,要被CPU执行时,操作系统就会将他的代码和数据从磁盘上的swap分区上唤入。
我们要提及的是唤出时,进程的task_struct不会被唤出,如果他被唤出,那么谁来记录这个进程的数据,我怎么知道你被唤出了,什么时候唤回来,所以我们的进程在创建时,也是先创建task_struct进程控制块,然后再将他的代码和数据加载进内存。我们说,一个进程要想运行,首先要加载到内存中被操作系统所管理,而要被操作系统所管理,就要先描述,再组织,也就是先创建他的PCB,在将他组织进一个数据结构,我们将来对进程的管理,也就转变成了对这个数据结构的增删查改。
再一个问题,swap分区的大小一般来说和内存大小相同,或者是内存的一半,如果swap分区过大,那么操作系统会依赖这个分区,因为他很大,我们理解成操作系统要将分区填满,所以操作系统一但有阻塞进程,就会把他的代码和数据唤出,或者其他状态下的进程唤出,而相对于CPU和内存交互的速度来说,内存向外设写入代码和数据的速度并不快,这样频繁的唤出,必然会导致整体效率的下降,以及整个操作系统的卡顿。
我们这里只是片面的提及挂起,挂起还有运行挂起等等,同时操作系统在计算机吃紧的时候,不会只去清理进程,还会去清理文件等等其他资源,这里我们只是管中窥豹来了解一下挂起。
所以最后,进程状态的本质,其实就是进程在不同队列的迁移,在运行队列,就是运行状态,在等待队列,就是等待状态,而队列迁移,状态也就改变,status这个变量的值也就改变了。(这里可以参考进程排队)
Linux下具体进程状态
接下来我们会具体说到Linux下进程的状态具体是怎样的
这是Linux内核的源代码
我们挨个介绍
R状态 和 S状态
R (running) 运行状态
S (Sleeping) 可中断睡眠状态
要说明的是博主开了两个窗口,不是一个窗口执行,为了字体大小方便读者看清,下面的图都是以一个窗口形式展现的,我们将编号,左边是零号窗口,执行和更改代码,右边是一号窗口,用于查看进程,以及杀死进程。
我们发现我们运行的程序处于S状态,(+号一会解释),为什么不是R状态呢?难道是因为进程执行太快了,我们还有sleep休眠1秒所导致的吗?我们去掉sleep。
CPU开始疯狂执行,这行代码开始刷屏,现在进程是什么状态呢 ?
为什么?我们知道printf是个输出函数,要执行他需要访问显式器,显示器是个硬件,访问他必然不会快,而CPU的执行又很快,于是进程到了运行队列,很快执行后,迁移到显示器的等待队列等待响应,这个过程相对于CPU来说就很慢了,于是我们在查询进程时,几乎都是阻塞状态,也就是S。
那么那个+号是什么意思?
这样有+号的进程就是前台进程,执行起来可以中断,输入指令不可执行。
这样执行起来的进程就是后台进程,执行起来不可中断,同时输入指令是可以执行的。
那我们怎么中断这个进程呢?使用指令kill -9 pid
-9是信号,意为杀死进程。
这个进程就被杀死了。
我们再运行一次查看他的状态,是S,也就是后台进程。
那么我们在删掉printf语句,能不能出现R状态呢?
D状态
D (disk sleep) 不可中断进程
这个我们无法演示,但是可以说明,这个状态也叫做磁盘休眠,也就是说一个进程在内存向磁盘写入代码和数据时, 该进程无法被操作系统终止回收,即使计算机资源吃紧,也不可唤出或者杀死。
需要说到的是,如果你的电脑能够查到这个状态,说明你的磁盘已经很满了,操作系统和你的计算机也快玩完了,因为在向磁盘写入数据时,再慢也不是我们能够感知的,同时还被操作系统查到了,说明你的电脑已经很卡顿了,也就快完了。
T状态
什么时候会出现T状态呢?就是进程想要访问某些硬件,但是硬件不允许,但是操作系统又不想杀死或者回收,就会出现这个状态,我们无法演示,但是可以通过信号来让进程暂停。
T (stopped) 暂停状态
恢复进程
我们kill -9 2472 杀掉进程即可。
t状态
t (tracing stop) 暂停状态
我们通过调试来展现这个状态。
此时我们直接跳到断点处,就是t中断状态。
Z状态(僵尸进程)
Z (zombie) 僵尸状态
进程在结束时会将他的task_struct数据返回给父进程,只有父进程读取了这些数据,这个子进程才会结束,如果不读取,就会处于僵尸状态,成为僵尸进程,不会被操作系统释放他的task_struct如果这样的进程很多,那么就会平白占据很多内存空间。
子进程在运行。
子进程变成僵尸,因为父进程一直没有结束,没有去读取子进程的数据。
我们平时为什么看不到Z状态呢?因为他们的父进程自动就回收了,计算机的速度很快,不要用我们的感受去衡量计算机的速度。
X状态
X (dead) 从Z状态退出就是X状态
这个不解释。
孤儿进程
如果父进程结束,但是子进程没有结束,子进程就会成为孤儿进程,被操作系统接管。
可以看到子进程后面被1号进程接管。我们可以查看一下1号进程,就是操作系统