您的位置:首页 > 其它

进程的状态以及状态转化图、导致转化的事件

2017-02-10 20:44 288 查看

今天又重新复习了一下进程方面的知识

进程的初始状态

进程是通过fork系列的系统调用(fork、clone、vfork)来创建的,内核(或内核模块)也可以通过kernel_thread函数创建内核进程。这些创建子进程的函数本质上都完成了相同的功能——将调用进程复制一份,得到子进程。(可以通过选项参数来决定各种资源是共享、还是私有。)那么既然调用进程处于TASK_RUNNING状态(否则,它若不是正在运行,又怎么进行调用?),则子进程默认也处于TASK_RUNNING状态。另外,在系统调用调用clone和内核函数kernel_thread也接受CLONE_STOPPED选项,从而将子进程的初始状态置为TASK_STOPPED。

进程状态变迁

进程自创建以后,状态可能发生一系列的变化,直到进程退出。而尽管进程状态有好几种,但是进程状态的变迁却只有两个方向——从TASK_RUNNING状态变为非TASK_RUNNING状态、或者从非TASK_RUNNING状态变为TASK_RUNNING状态。也就是说,如果给一个TASK_INTERRUPTIBLE状态的进程发送SIGKILL信号,这个进程将先被唤醒(进入

TASK_RUNNING状态),然后再响应SIGKILL信号而退出(变为TASK_DEAD状态)。并不会从TASK_INTERRUPTIBLE状态直接退出。进程从非TASK_RUNNING状态变为TASK_RUNNING状态,是由别的进程(也可能是中断处理程序)执行唤醒操作来实现的。执行唤醒的进程设置被唤醒进程的状态为TASK_RUNNING,然后将其task_struct结构加入到某个CPU的可执行队列中。于是被唤醒的进程将有机会被调度执行。

而进程从TASK_RUNNING状态变为非TASK_RUNNING状态,则有两种途径:

响应信号而进入TASK_STOPED状态、或TASK_DEAD状态;

执行系统调用主动进入TASK_INTERRUPTIBLE状态(如nanosleep系统调用)、或TASK_DEAD状态(如exit

系统调用);或由于执行系统调用需要的资源得不到满足,而进入TASK_INTERRUPTIBLE状态或TASK_UNINTERRUPTIBLE状态(如select系统调用)。

显然,这两种情况都只能发生在进程正在CPU上执行的情况下。

4000
为了对进程从产生到消亡的整个过程进行跟踪和描述,就需要定义各种进程的各种状态并制定相应的状态转换策略,以此来控制进程的运行。

不同的操作系统对进程的状态解释不同,但是最基本的状态都是一样的。包括一下三种:

运行态:进程占用CPU,并在CPU上运行;

就绪态:进程已经具备运行条件,但是CPU还没有分配过来;

阻塞态:进程因等待某件事发生而暂时不能运行;

进程在一生中,都处于上述3中状态之一。

下面是3种状态转换图



当然理论上上述三种状态之间转换分为六种情况;

运行---》就绪:这是有调度引起的,主要是进程占用CPU的时间过长

就绪---》运行:运行的进程的时间片用完,调度就转到就绪队列中选择合适的进程分配CPU

运行---》阻塞:发生了I/O请求或等待某件事的发生

阻塞---》就绪:进程所等待的事件发生,就进入就绪队列

以上4种情况可以相互正常转换,不是还有两种情况吗?

阻塞--》运行:即使给阻塞进程分配CPU,也无法执行,操作系统載进行调度时不会載阻塞队列进行挑选,其调度的选择对象为就绪队列:

就绪--》阻塞:因为就绪态根本就没有执行,何来进入阻塞态?

现在知道了进程的三种基本状态,但是載操作系统具体现实中,设计者可以根据实际情况设置不同的状态,这样以来,就出现了以下几种状态:

可运行态:他是运行态和就绪态的合并,表示进程正在运行或准备运行,Linux 中使用TASK_RUNNING 宏表示此状态。

浅度睡眠态:进程正在睡眠(被阻塞),等待资源到来是唤醒,也可以通过其他进程信号或时钟中断唤醒,进入运行队列。Linux 使用TASK_INTERRUPTIBLE 宏表示此状态。

深度睡眠态:其和浅度睡眠基本类似,但有一点就是不可其他进程信号或时钟中断唤醒。Linux 使用TASK_UNINTERRUPTIBLE 宏表示此状态。

暂停状态:进程暂停执行接受某种处理。如正在接受调试的进程处于这种状态,Linux 使用TASK_STOPPED 宏表示此状态。

僵死状态:进程已经结束但未释放PCB,Linux 使用TASK_ZOMBIE 宏表示此状态。

我们可以来看下以上宏在内核中的定义:

#define TASK_RUNNING            0

183 #define TASK_INTERRUPTIBLE      1

184 #define TASK_UNINTERRUPTIBLE    2

185 #define __TASK_STOPPED          4

186 #define __TASK_TRACED           8

187 /* in tsk->exit_state */进程的退出状态

188 #define EXIT_ZOMBIE             16

189 #define EXIT_DEAD               32

190 /* in tsk->state again */我理解为进程的唤醒状态

191 #define TASK_DEAD               64

192 #define TASK_WAKEKILL           128

193 #define TASK_WAKING             256

194 #define TASK_STATE_MAX          512

195

196 #define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW"

以下是LINUX进程间状态转换和内核调用图解

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐