接下来我们讨论进程的状态
进程的状态呢是指操作系统为了
维护进程执行的过程当中的
所有信息的变化
那它有必要知道进程
在执行过程当中会出现哪些状态
它会在什么情况下会发生变化
那这是呢我们对进程
在整个生命周期当中
它可能出现的一些事件的划分
这种划分呢在不同的
操作系统当中它会不一样
比如说在我们这里头
把它划分成创建
有可能你需要其中一个程序执行
那这个启动过程
就会导致一个新的进程的创建
那创建完了之后呢
它就会是程序进入执行的状态
这是第二个
它会占用CPU来执行
在执行的过程当中它可能会由于
等待某个资源或者
等待某个数据而进入等待状态
好那这个时候呢
就导致进程进行等待
好在执行的过程当中
还会有另外一种情况
你比如说
我一个优先级低的进程正在执行
这时候有一个高优先级的进程
有等待状态结束
就是它等待的条件已经成熟了
已经满足了
好那这时候它要马上开始投入运行
有可能我当前这个进程是会抢先
那这时候呢我这个
先进入就绪状态这个进程叫抢先
而当前正在执行这个进程呢
叫做被抢占
好那处于等待状态的进程呢
它会碰到被唤醒的情况
在外界条件满足的时候它会被唤醒
唤醒之后呢
又排到这个就绪队列里头
也就说它等待占用CPU来继续执行
那等最后回到CPU上执行
执行到最后的某种状态呢
整个程序的工作全部执行完
那就有可能进到进程结束的状态
那这时候到达结束
那整个呢这是我们在这里头
对进程的生命周期的一个划分
这种划分呢在不同系统里呢
会有一些变化
大致的情况呢基本上就是这几种
那我们具体来讨论一下
这些状态的变化
首先一个进程创建
要创建一个进程
实际上我们在前面说
每一个进程有一个进程控制块
那这些相关的它要占用内存
把代码和数据都拷进去
这些资源的准备过程
就对应到我们这里进程创建
那可能导致创建的事件呢
有这样几种
第一个系统初始化
初始化完成之后
我要创建第一个用户进程
那这是一种情况
然后在用户进程执行的过程当中
我可能会要执行某项功能
用户请求创建一个新的进程
那实际上这个请求过程呢
也会导致一个程序
我会执行创建进程的系统调用
这是我们操作系统对上
提供的创建进程的API
好创建好了这个进程之后呢
我们就会放到内核里的
就绪队列里头
这时候进程控制块呢
就排到这个就绪队列里头
好那等待CPU调度
那如果说这个处理机
没有其它进程运行
那我就会调度一个
新的进程来运行
这时候调度呢就会
导致我这个进程进入运行状态
那我如何来选择一个
就绪进程来运行
如果说你只有一个那我就选择它
如果有多个我怎么选择
那实际上这种选择的依据呢
就是我们后面会讲到的
处理机的调度算法
那不同的调度算法系统会体现出
不同样的进程执行的特征
好在执行的过程当中呢
有可能进程执行的
某一项条件不成立
需要等待的某个数据
或者说外部资源不足够
那这时候呢
我进程会进入等待状态
那这种等待状态呢
可能的原因是说
我等待的系统的服务
并没有马上完成
或者说我启动的某个操作
比如说我读写磁盘
那这个读的过程呢
它并不能在很短的时间里给出来
因为我指令执行的速度
是远高于我磁盘读写的速度了
好再有一个就是
我等待需要的数据没有到达
那这些都会导致
我进程进到等待状态
一旦这些等待事件出现之后
它就会回到这儿
那么在这中间呢还会再有一种情况
在这里呢等待事件的进入一定是我
正在运行这个进程
本身内部的原因所导致的
它不是由于外部原因
所导致它进入等待状态的
好在执行的过程当中呢
还有一种可能的变化
就是我正在运行的进程被抢占
那这种情况呢会出现在
我有高优先级的进程变成就绪
它需要马上投入运行
那会把我正在运行的这个进程呢
变成就绪然后让它运行
第二种情况呢是说
我们在操作系统里头它的调度算法
为每个进程分配了
它可以执行的最长时间
如果你分配的这个时间片用完了
那这时候呢
系统
操作系统内核会强制把这个进程呢
抢先让下一个进程投入运行
那这是呢时间片在这里起到的作用
好那这个地方呢是说
我在什么情况会回到就绪状态
那就是说我进程被唤醒
那唤醒的可能条件呢是
我们刚才进入等待的
那几个条件的反过来
我等待的资源满足了
我等待的事件出现了
那都会出现这种情况
而和这个等待进入相反
唤醒的条件呢
一定是被其别的进程或者
操作系统唤醒
它不会是由于自身的原因直接回去
那这是呢在这里唤醒的时候的情况
那在执行的过程当中
还有一种情况呢是说
我在执行到整个进程
执行结束那我要退出
这是要干什么呢
要把进程执行所占用的
所有资源还给操作系统
以便于它能把它分配给
新的进程使用
如果没有这个过程的话
那分配出的资源就会丢掉了
那在这个过程当中呢
结束呢有这样几种情况
这是我们希望的正常退出
那在正常退出之外呢
还有一些意外的原因
你比如说出现错误
错误呢分成一般的错误
我可以做收尾的
那就是错误退出
有一些错误是没有任何理由
它直接就跑不动了
那这就是致命性错误
那这时候呢你可能这个收尾工作
就做的不是很完善
还有一种情况就是
你在执行过程当中
其他的进程认为你有问题
那可能这种认为也不一定是正确的
好它强制把这进程杀掉
那这是几种我们
从运行到退出的情况
那有了这些说明之后呢
我们关于进程的状态的变化情况呢
就有一个基本的了解
那下面呢我们通过一个小例子
来说明进程状态的变化情况
那在这里头呢我们假定
我写了一个小程序
这个小程序呢进来之后
执行的主要操作就是
延时两秒然后结束
那在这个小程序呢
它会什么样状态
首先我启动这个小程序的时候
它会有创建
创建呢去分配
这个进程执行所需要的资源
你比如说内存
好相关的数据结构初始化
完成之后那这就进入就绪状态
进入就绪状态呢是说
我把这个进程所创建的
包括进程控制块
挂到就绪队列里头去
好然后在就绪队列里头等待
占用CPU的进程结束退出
或者说被抢先
好然后这时候呢
在CPU的调度下它就可以
从这儿进到占用CPU来开始执行
在执行的过程当中会执行到
你的sleep这个系统调用
这个调用呢它设置好定时器
那这时候呢它就没事干了
因为我们延时两秒
中间这两秒它是做不了任何事情的
好在这两秒钟的时候呢
那它就会进到等待状态
那等待状态结束呢
是说我这边的在内核里
它的sleep操作会设定时器
定时器在两秒钟到了之后呢
它会给系统一个中断
好这个中断呢会导致系统说
这个中断是原因是什么
最后找到这个进程
好通知它
它可以进到就绪状态
好那这时候操作系统内核代码
会把这个处于等待状态的进程呢
放到就绪队列里头去
并且把它的等待事件设置为出现
好然后等待CPU调度
就处于就绪状态
好等到它可以占用CPU来运行的时候
那又进到运行状态
那到这儿呢我们这个基本的操作
就执行的差不多了
接下来是说它要退出
然后把它所占用资源全部还回去
那我这个进程的整个生命周期呢
就全部完成了
那我们所有的程序在执行过程当中呢
我们操作系统需要对这个过程
进行全面准确的把握
只有这样的话我才可以知道
我这个进程执行的情况
那么在这个里头呢
我们还会涉及到一个问题是说
我一个进程进入等待
或者说被抢先或者说结束
我都需要找另一个进程来继续运行
那这时候就有一个进程的切换
那这是我们在内存当中
当前正在交替运行的N个进程
那这个切换的过程是怎么进行的呢
我们在这里头进程一进程二
我们假定有两个进程
好首先呢假定跟我刚才例子一样
它进到这里头执行sleep
这时候呢会导致进入内核
这仍然算是这个进程执行的时间
好然后呢
内核里头会调用函数设置定时器
那这是这边设备
这个设备呢可以和
我们CPU呢同时运行
这是并行的好
设置好了定时器之后呢
那我这个程序就走不下去了
那它就会执行调度
这个调度呢会把
当前的进程的
占用的寄存器的状态呢
都保存到进程控制块里头
然后它这时候切换到第二个进程
这是从就绪队列里找出来的
然后让第二个进程呢开始运行
那在这个运行的过程当中
它可能会是说
你的这个定时器的时间到了
这个时候定时器呢会产生一个中断
这个中断呢会在这里做响应
这个响应的操作是
让这个进程暂停下来
并且保护进程二的现场
恢复进程一的现场
恢复完毕之后让进程一继续执行
那么等到这个进程执行结束呢
它就再回到操作系统
这相当于我们最后那个
结束那个进程
好那实际上我们在
这个整个操作系统
在掌控内部正在运行
所有进程运行过程呢
就是从一个切到另一个
再从另一个再切回来
周而复始的这样来切换
那这是进程切换的情况