进程状态(一)---- 运行,阻塞,挂起
创始人
2024-11-15 17:36:18
0

目录

  • 前言
  • 1. 运行状态
  • 2. 阻塞状态
  • 3. 挂起状态

前言

接着上一篇文章 进程概念(三) 讲到,我们了解到了进程属性中的 PID,也了解了 ./test 这是在系统层面上系统自动创建的进程,进而初始 fork ---- 代码层面上手动创建进程,以及关于 fork背后的一些原理,而这篇文章,我们主要介绍进程状态当中的运行、阻塞、挂起。

R 运行状态(running):  并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。 S 睡眠状态(sleeping):  意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。 D 磁盘休眠状态(Disk sleep): 有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。 T 停止状态(stopped):可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。 X 死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。 

接下来我们会较为详细的介绍什么是运行、阻塞、挂起状态

1. 运行状态

众所周知,存在于系统中的进程并不是一个两个,可能十几个,甚至几十个,上百个进程。而操作系统为了方便管理这些进程,对待进程都是 “先描述,后组织” 的理念,而其中的 PCB 在操作系统中都是以双链表的形势被组织起来的。但是,进程有多个,CPU 一般只有一个啊,所以就一定存在一种现象,众多的进程一定要竞争这一个 CPU 的资源。而先运行谁,是调度器说了算,但是调度器也要保证,CPU 的资源被合理的使用。所以每个 CPU 都要维护一个类似如下的运行队列:

struct runqueue { 	// 运行队列 	struct task_struct* head;	 	struct task_struct* tail; 	...... } 

而进程想要被 cpu 执行,那么就需要先被列入到运行队列当中,然后在队列中排队(排队的是 PCB,而不是这个进程的代码和数据),所以 cpu 想要执行某个进程,就直接从运行队列中的队头进程拿去运行就可以了。而调度器可以理解为一个函数,将运行队列作为参数传递给调度器之后,调度器就可以通过 head 和 tail 指针找到所有在排队的进程。所以凡是处于运行队列当中的进程,这些进程的状态,称之为 运行状态 (也即运行态)( R )。

问题一:一个进程只要被CPU开始运行了,就一直到执行完毕才会停下来吗?
不是的。如果是这样的话,那么当我们代码中存在 while(1) 这样的死循环的时候,那么这个进程就会一直被 CPU 执行下去,反之,其它进程就无法被 CPU 进行调度运行,我们看到的应该是其它进程一直处于 “卡着不动” 的状态。但事实上,我们最多就是感觉到多了一点卡顿,并不至于无法正常运行其它的进程。

所以为了防止某个进程一直赖在 CPU 上面不下来的情况,每个进程都有一个叫做 时间片 的概念(比如一次调度最多执行 10ms,之后就会被重置到运行队列的队尾重新排队等待调度)。这样就可以使得,一段时间内,所有的进程都会被调度运行。所以这样就会出现大量的进程从 CPU 上放上去,再被拿下来的动作,而这个过程我们称为 进程切换。而 cpu 的速度是非常块的,即使 cpu 不断的进行进程切换,我们肉眼也无法有所察觉。

2. 阻塞状态

在操作系统的底层中,存在各种设备(键盘,鼠标,网卡等),而这些设备也称为外设。对于系统而言,无非就是从外设做读取数据,或者将内存中的数据写入到外设中。而之前的文章里面,我们已经谈到了操作系统是一款对软硬件资源做管理的软件,而之前所说的操作系统对进程做管理,而进程背后的本质就是软件(系统中的进程的本质可以理解为代码和数据,PCB也是由操作系统创建出来的结构体对象),所以对进程做管理,就是在对软件做管理。对进程做调度管理,有运行队列,那么操作系统对硬件做管理,有什么呢?又或者操作系统是如何对硬件做管理的?

只要是管理,就是 “先描述,再组织”,所以硬件也是如此。所以系统对进程的描述可以类似如下:

 struct dev(网卡/键盘/鼠标)  {  	int type;  	int status;  	struct task_struct* waitqueue;  } 

所以面对各种各样的设备,操作系统都可以以结构体的形式进行描述,再以链表的形式将这些外设链接起来。假设今天我们所编写的 C 语言,我们要从键盘当中读取数据,但是当我调用了 scanf 之后,我就是不输入。那么这个进程就无法在运行队列中排队等待调度,因为此刻这个进程需要访问的是键盘这个外设,而我们不输入,就相当于这个外设还没有准备就绪,那么这个进程就需要等待外设资源,所以它就会被链入到键盘这个设备的等待队列中,而不是在运行队列中等待调度。如果后续还有其它进程也需要键盘这个外设资源,它也到键盘的等待队列中进行排队,直到驱动程序发现从键盘当中读取到数据了,系统就会将原本处于键盘的等待队列中的进程,放入到 cpu 的运行队列中排队等待调度。所以我们将正在等待特定设备的进程,我们称为 这个进程处于阻塞状态!

不过,与运行队列不同的是,一个操作系统中,如果 cpu 只有一个,那么它一定只有一个运行队列。但是阻塞队列可能有十几个,几十个甚至更多,因为每一个设备都有自己的等待队列,而进程中也可能存在等待队列。

所以什么是阻塞状态? ---- 当一个进程需要访问某种资源的时候,但是该资源没有就绪,那么只需要将这个进程的 PCB 链入到这个设备的等待队列中即可,而处于等待队列中的进程,称为阻塞状态。当资源就绪时,操心系统会对正在处于等待队列中的进程进行唤醒,而唤醒的本质就是,将进程的阻塞状态改为运行状态,然后放在运行队列中,这就叫做进程唤醒。

3. 挂起状态

假设现在操作系统内部的内存资源严重不足了,但是操作系统发现,有很多的进程在等待着某个设备,处于阻塞状态中。而操作系统需要保证系统的正常运行,现在内存不足了,它就得想办法把内存资源腾出来。我们需要知道的是,处于阻塞状态的进程,它的代码和数据在内存中是处于空闲状态的(就是没有被执行)。于是,在操作系统内存资源严重不足的情况下,就会将处于等待队列中的进程的 pcb 在内存中保留,而进程的代码和数据就被交换到磁盘等外设当中(这个过程我们称为换出)。 等到资源就绪了,系统再重新考虑将这个进程的代码和数据重新写回到内存当中,而这个过程我们称为 换入。所以这种只有 pcb 在内存中,而它的代码和数据被换出到外设的进程,我们称为 挂起状态。而在这些进程等待某种资源的就绪时,这些被换出的空间,操作系统就可以分配给其它有需要的进程使用。而操作系统也不会针对部分进程这么做,这种策略,针对系统中所有正在处于阻塞状态的进程!


上述这三种状态,都是操作系统学科所涉及到的三个进程状态,后续我们会进一步谈论 linux 系统当中是如何维护这种进程状态的,在 linux 当中,运行状态是什么,阻塞状态又是什么,挂起状态又是什么?后续文章也会谈论操作系统的状态和具体的 linux 操作系统的状态有什么异同。

如果感觉该篇文章给你带来了收获,可以 点赞👍 + 收藏⭐️ + 关注➕ 支持一下!

感谢各位观看!

相关内容

热门资讯

【单片机毕业设计选题24095... 系统功能:系统上电后,OLED显示三组18650锂电池电压。第一行显示第一组锂电池电压...
Django函数视图和类视图 函数视图1.全局环境的urls.py引入映入应用的urls,避免后期开发路由过多而导致...
C#中WebView2调用与交... 简要说明:此控件实际上是 [WebView2 COM API] (htt...
AI大模型需要什么样的数据? 数据将是未来AI大模型竞争的关键要素人工智能发展的突破得益于高质量数据的发展。例如,大...
基于SpringBoot+Vu... 基于SpringBoot+Vue的多媒体信息共享平台(带1w+文档)基于Spring...
2024年人工智能顶级会议投稿... 数据挖掘是信息科学领域的重要分支,致力于挖掘和分析庞大数据集中的有价值模式与规律。它融...
终于来了,Runway gen... 最近有好几个学员私信我们,让我出一期Runway完整的使用教程,刚好11月Runway对外发布运动涂...
人工智能搜索引擎 Perple... Perplexity AI是一款革命性的人工智能搜索引擎,结合传统搜索索引与大型语言模...
AI大模型探索之路-实战篇14... 系列篇章💥AI大模型探索之路-实战篇4:深入DB-GPT数据应用开发框...
k8s核心知识总结 写在前面时间一下子到了7月份尾;整个7月份都乱糟糟的,不管怎么样...