【操作系统】一篇文章带你快速认识Linux中的进程状态!

🎬 乀艨ic:个人主页

⛺️这次更新还是比较快的吧()

⭐️来看看这次的博客吧~


🌳前言

发现Linux的点击量真的很多,那就再更几篇Linux相关的吧()
注:Linux的不同发行版本的指令可能有所不同,本次是按照CentOS7的标准来进行追述的。

在这里插入图片描述

🌳进程状态抽象概括

我们先来看一下一般讲进程状态时会谈到的五种状态,分别是创建、就绪、运行、阻塞和终止状态
但由于现在的操作系统大多都不会按照这个说法去实现,因此我们注重讲述几个概念之后去看一下Linux的内核代码写法。
在这里插入图片描述

🌲运行

现在由于硬件 CPU 的不断迭代更新,创建状态已经相当的迅速,导致在很多操作系统中就已经不再考虑设计这个状态,同时,在 Linux 中也将就绪状态跟运行状态统称为运行状态。

我们明确一个概念,每一个硬件都会存在一个队列,而所有的进程的 PCB 都会在队列中去排队等待资源,同样的 CPU 也会存在一个运行队列,而所有等待 CPU 资源的 PCB 会挂在队列上,在 Linux 中就称这个状态为运行状态。

在 Linux 中 CPU 会按照运行队列中的顺序去挨个去调度排队的进程(具体的调度算法可以看后续的文章(挖坑ing))。在 Linux 中将在 CPU 运行队列中的所有进程状态就标记为运行状态

在这里插入图片描述
如上图,可以看一下简单的逻辑图。

🌲阻塞

在谈完运行的概念之后,我们再来看看什么是阻塞。阻塞状态从核心的角度去谈,就是进程正在等待软硬件资源,而将自己的 PCB 链接到等待的资源所提供的等待队列中。

比如说当我使用C语言中的 scanf 函数的时候,如下图:
在这里插入图片描述
此时此刻由于该进程正在等待我的键盘资源去提供输入,Linux 就会把该进程放到键盘的等待队列中,这个时候该进程的状态就是阻塞状态。

所以可以这么说:

状态的变化本质是OS将PCB放到了不同的队列中。

🌲挂起

最后我们谈一下挂起状态。达到挂起状态有一个很大的前提,是内存资源已经非常吃紧的情况下,操作系统会考虑将内存中的一部分数据暂时放到磁盘中的一块叫做 swap 分区的地方来缓解压力。
注:不只是将进程跟自身 PCB 放到 swap,同时也会处理在内存上的一些其他数据去缓解压力。
如下是逻辑示意图:
在这里插入图片描述
也可以通过 free 指令去查看内存的使用情况跟自身的 swap 分区,如下:
在这里插入图片描述

🌳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 * 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 磁盘休眠状态(Disksleep): 有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
X 死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

🌲进程状态查看

我们再来看看在Linux中怎么去查看一个进程的状态:

ps aux / ps axj 命令

如下图所示:
在这里插入图片描述
当然也可以通过ps ajx 与 grep 去联合获取指定进程的状态。

下面是 Linux 的进程状态模型。

在这里插入图片描述

🌲僵尸进程

我们来具体谈一下僵尸状态:

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(需要使用wait()系统调用去回收子进程的退出码)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

我们来直观看一下:

在这里插入图片描述

上述代码会在开始由父进程去创建一个子进程,5秒之后会将子进程杀死变成僵尸状态,同时不让父进程去回收子进程的 PCB 数据,我们通过状态查看去看一下:

在这里插入图片描述

可以看到子进程从开始的 S 状态变成了 Z(僵尸)状态,而且后面仍然维持着该状态。

🍃僵尸进程的危害

进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就要一直处于 Z 状态。
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在 task_struct(PCB) 中,换句话说, Z 状态一直不退出,PCB 一直都要维护而不能回收。
那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费。因为数据结构对象本身就要占用内存,在 C 语言中去定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间,而 PCB 一直不被回收就会导致内存泄漏。

在这里插入图片描述

🌳结尾

这就是Linux状态的相关内容了,以后还会更新关于 Linux 的进程调度与进程控制等相关知识对本文的内容进行补充,点一个关注避免错过哦~

感谢观看,喜欢的话可以给一个大大的三连哦~
期待我们的下次相遇,喜欢的请点个关注再走哦!之后会持续更新更多的内容!
个人主页:传送门

在这里插入图片描述

  • 31
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值