进程的状态,二状态、五状态、七状态进程模型以及Linux中的各种进程状态
进程状态模型
进程状态模型
二状态模式
该模型将进程所处的状态划分成:运行态、未运行态。
五状态模型
如果系统中所有的状态都做好了执行准备,那么上面的模型是有效的。但是这样的模型过于简单。设想,如果队列中有一个进程因为等待某个事件就绪,而处于阻塞态……那就巴比Q了
所以为了更加合理、且高效地利用CPU资源,我们应该将进程所处的状态细化。就好比,学校跑步测试,运动员的状态被划分为就绪状态、未就绪状态,跑步状态、考完状态……,如果运动员处于考完状态、那么就不用管他了,如果运动员处于就绪状态,就准备让他先跑……这样就能根据运动员的状态来最高效地利用测试资源。
接下来我将继续使用跑步测试的例子讲解。
五状态模型把进程所处状态划分为:
- 运行态
- 就绪态
- 阻塞态
- 新建态
- 退出态
运行态:
该进程正在执行。好比跑步测试时,运动员正在跑步。
就绪态:
该进程的条件已经准备好,做好了被执行的准备。好比跑步测试,测试时的各种条件都准备好了,运动员也准备好了测试,只等待跑步开始。
阻塞态:
进程在某些事件发生前不能执行。好比跑步测试,你需要带上测试的衣服才能去准备区等待,但是体育老师还没有给你发放,而你没有穿测试的衣服,所以还不能准备跑步。
新建态:
也称初始态,指的是进程才被创建好,但是还没有加载到主存储器里。好比跑步测试,你刚刚才报名的跑步测试,学校还没有为你准备,也没有把你的资料传给负责这跑步测试的人/组织。
退出态:
【进程模型中的队列】
处于就绪态的进程被放入:运行队列、又可以称为就绪队列。
处于阻塞态的进程被放入:阻塞队列,又可以称为等待队列。
七状态进制模型
利用五状态模型已经能很好地利用CPU的资源了,但是还可以更进一步地优化。
模型中的处于其中四个状态的进程都被加载到内存里面了,设想:系统中此时如果同时存在大量的进程,然而内存(主存)存储空间是有限的,远远没有外存的存储空间大。就极大可能存在,一些在等待某些事件发生的进程一直占据着内存空间,导致很多处在外存的进程不能加载到内存里,因为已经没有容纳这些进程的存储空间。
以上的解决办法有两种:
- 🥣增加主存容量
- 🥣交换空间。
推荐第二种方法。
交换空间,实质把主存中的把空间腾出来,让给那些还没有加载到主存的进程。
相当于是把让某些进程晾在一边(挂在一边),让它在外面等待某些事件发生,或者让它在外面等待被执行。好比跑步测试时,操场的容量是有限的,可以让操场里还没有做好准备或者等待着某些事件发生的运动员,转移到操场外面,而让操场外面有条件的运动员转移到操场上。
这些进程所处的状态就变为“就绪/挂起态”,或者“阻塞/挂起态”。
【区分】
🍭就绪态:进程被加载到主存里,在运行队列(就绪队列)中,随时准备被执行
🍭阻塞态:进程被加载到主存里,在等待队列(阻塞队列里)中,等待着其他必备事件的发生。
🍭就绪/挂起态:进程在外存(辅存)里面,在挂起队列中,等待着其他必备事件的发生。
🍭阻塞/挂起态:进程在外存(辅存)里面,在挂起队列中,随时准备加载到主存里执行
挂起状态的进程特点:
1.不能被立马执行
2.在等待某些事件的发生
3.不想被执行。
第三个特点是很巧妙,不想被执行的进程可以把它转变为挂起进程,通过代理(进程本身、父进程或者操作系统),把它的状态转变为挂起状态,一旦被转变为挂起状态,就不能从这个状态转换成其他状态,除非代理显示地转化该进程的状态。
Linux中的进程状态
上面所述的二状态进程模型,五状态进程模型,七状态进程模型,是系统的基本进程状态的模型,既然是模型,那么不同的操作系统可能会略有不同,一起看看Linux操作系统的各种进程状态吧。
下面是Linux描述进程状态的结构体,这个结构体在Linux的进程控制跨块task_struct
中
/*
* 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,代表运行状态. 这里的R对应模型中的等待状态/运行状态 -
S
:理解为sleeping的缩写,代表睡眠状态.对应模型中的阻塞状态,他必须等待事件。 -
D
:理解disk sleep的缩写,代表深度睡眠状态。是因为受到内核指示而停用的睡眠进程,外部信号无法唤醒它们,只能有内核来亲自唤醒 -
T
:stopped的缩写,代表暂停状态。进程特意停止运行的状态,比如调试器暂停来进行调试操作的时候。 -
t
:tracing stop的缩写,它本来不是一个进程的状态,就是用来区分处在暂停状态的进程,看它是否是被调试的进程还是常规的暂停。 -
Z
:zombie的缩写,代表僵尸状态
提到僵尸我也看过很多僵尸片了,按照我们的说法,僵尸的特点是,它既死了又活着,只不过是没有灵魂的活着 。而僵尸状态的进程也是如此,这个进程即死了又活着。说它死了是因为它的资源已经被释放了,那么也就不能再次运行;说它活着,是因为进程表里面还有它的PCB,也就是还含有这个进程的各种属性信息。它没有真正地被终止。
判断一个程序是不是真正地终止或者退出了,要看两个方面
1】程序被另一个进程或一个用户杀死
2】内核已经释放为进程保留的资源。
当一个条件符合,而第二个条件不满足时,那么就会出现僵尸状态。
Z
:死亡状态。真正地终止了
接下来看一看Linux中进程的各种状态吧。
现在有如下程序
//mycode.c文件
1 # include <stdio.h>
2
3 int main(void)
4 {
5 while(1)
6 {
7 ;
8 }
9 return 0;
10 }
开始在终端执行这个程序。
复制会话,然后查看该进程
发现它一直处于R状态。
//mycode.c
1 # include <stdio.h>
2
3 int main(void)
4 {
5 while(1)
6 {
7 printf("hello\n") ;
8 }
9 return 0;
10 }
但是现在在运行,会发现它大多数时候都是S状态,这是因为涉及到了IO操作,相对于CPU来说,IO简直太慢了,所以这个进程大多数都在等待IO设备的就绪。
其他的你们自行测试吧。
【孤儿进程】
还有一种特殊的进程,孤儿进程。
孤儿进程,当一个进程的父进程,在该进程还没有终止前父进程就提前终止了,那么该进程就变成了孤儿进程,孤儿进程会被init进程(1号进程)“领养”
更多推荐
所有评论(0)