OS进程管理
进程:指一个具有一定独立功能的程序在一个数据集合上的一次动态执行的过程。
简单来说,进程就是正在内存中运行的程序。需要注意的是,不同进程之间的地址空间是相互独立的。
进程控制块(Process Control Block,PCB)
PCB是OS来描述进程基本情况及变化的一个数据结构,每个进程都在OS中对应有一个PCB,是进程存在的唯一标志。
PCB中主要包含以下信息:
- 调度和状态信息:即调度进程和处理机的使用情况
- 进程间通信信息:进程间通信相关的各种标志信息
- 存储管理信息:指向进程映像存储空间数据结构
- 进程所用到的资源:例如进程中需要使用到的文件资源等
- 有关数据结构的连接信息:与PCB相关的进程队列
一般来说,PCB的组织方式分为两种:链式
和索引式
,这个大家肯定都很熟悉,需要注意的两点是:
- 如果是索引的方式,会存在一个索引表,索引表的每一项指向其对应的PCB的起始地址。
- 不同的进程状态对应不同的PCB链表或PCB索引表。例如,我们都知道进程有
Ready态
、Waiting态
、Blocking态
,如果采用索引的方式来建立PCB组织方式,于是会有对应的就绪态索引表
、等待态索引表
。
进程的状态
说明一点:下面所有提到的等待
,你可以认为与阻塞
等价
说到进程,必然会涉及到上面这个图,下面简要概况一下各个箭头之间的转变情况,以及主要由什么原因产生的状态转化:
- 创建$\rightarrow$就绪
这里一般涉及的是进程额初始化,当然包括最开始开机的时候系统进程的初始化和用户请求创建一个新进程,或者是正在运行的进程执行了创建进程的系统调用,如fork()
系统调用。 - 就绪$\rightarrow$运行
当进程创建完毕,且一切需要的资源都准备就绪后,就可以由OS进行调度进入到运行状态,占用CPU时间片。 运行$\rightarrow$等待
为什么会有这个状态转化呢?试想一下,一个进程执行过程中涉及到文件IO操作,而磁盘的读取速度相较于CPU执行速度是很慢的,于是没必要一直忙等Busy Wait
,于是就可以将该进程阻塞起来,让它处于等待状态,等待的过程中把CPU时间片交给其他的进程去执行。
OK,至于引起进程阻塞的情况,大致有下面这几种情况:- 请求并等待系统服务,无法立马完成
- 启动某项操作(IO操作),无法立马完成
需要的数据没到达(例如计算一个数据很耗时)
==注意:一定是进程自身才能将自己阻塞,因为只有进程自己才知道何时需要等待某种事件的发送。==
- 等待$\rightarrow$就绪
既然有阻塞,那肯定也有解除阻塞,这一般被称为进程唤醒
,当进程被唤醒后,不是直接从等待态转化为运行态,而是需要先转到就绪态,再等待OS的调度。
==注意:进程只能被别的进程或OS唤醒,自己是不能唤醒自己的。== - 运行$\rightarrow$就绪
进程分优先级,如果一个比当前正在执行进程优先级高的进程到来时,它有特权,OS会优先让它执行。此外,有可能是进程自己请求睡眠一段时间sleep(1000)
,这也会引起进程转到就绪态去。 - 运行$\rightarrow$退出
这个就比较好理解了,进程运行完结束。但同样,这里有可能多种情况引发进程退出:- 正常退出(自愿的)
- 出现错误退出,例如产生了一个异常(自愿的)
- 致命错误,例如,一个进程企图访问其他进程的地址空间,这绝对不行!(强制性的)
- 被其他进程所杀(强制性的)
进程挂起(suspend)
我之前写过关于OS内存管理的博客,如果你对内存管理概念有些遗忘,可以浏览一下>>传送门<<
进程挂起指的是将处于内存中的进程映像到磁盘上去,目的是为了减少进程占用内存空间,这也和OS的内存管理、虚存管理息息相关。引入进程挂起后,进程的状态转化图中就会多了几个状态(等待挂起
、就绪挂起
)和引发状态转化的事件(挂起
、激活
等),如下图所示:
挂起相关状态
- 等待挂起状态(blocked-suspend)
进程等待某件事件的发生(即处于阻塞的情况),但这个时候,进程不是在内存中等,而是在外存中等待某件事件发生。 - 就绪挂起状态(ready-suspend)
进程在外存中就绪,只要进入内存,就可以被OS调度
挂起相关事件
- 挂起(suspend):把一个进程从内存挂起到外存中去 。
- 等待到等待挂起
为什么会出现这种情况?试想,假如现在内存中很多进程都处于等待状态,这些等待进程都是占用了内存空间的,而OS去调度想让一个进程运行时,内存又不够了,怎么办? 那就把一些处于等待状态的进程挂起到外存中去,这就是等待到等待挂起。 - 就绪到就绪挂起
这和上述等待到等待挂起是一个原理,既然你可以把一些处于等待状态的进程挂起到外存中去,为什么不可以将一些处于就绪状态的内存挂出去呢?是的,OS会根据处于等待状态进程的优先级,那些高优先级的(OS认为它很快就会从等待状态被唤醒,即所等待的事件很快就会完成),可能就不会被挂起到外存中去。取而代之,将一些就绪状态的进程外挂出去。 - 运行到就绪挂起
这个比较特殊,有些分时抢占式的OS,当有高优先级到来时,有可能将正在运行的进程之间挂起打就绪状态去,转而立马执行这个高优先级的进程。 - 等待挂起到就绪挂起
这时是因为正在等待的时间完成了,而此时进程又是出于外存中,所以需要把它的状态信息改变一下。
- 激活(activate):把一个进程从外存换入到内存
- 就绪挂起到就绪
当就绪队列中没有进程,或者就绪挂起队列中有进程优先级比就绪队列中进程的优先级高时,就会把这个进程从就绪挂起状态转为就绪状态。 - 等待挂起到等待
当一个进程释放了足够的内存时,系统会把一个高优先级等待挂起进程转为等待进程。.
这里涉及的状态比较多,建议多看几遍。如果通过上述文字很难理解,可以去看下陈渝老师的视频讲解>>传送门<<
进程状态队列转化示意图
需要注意的是,在等待队列中,如果有多个进程都在等待一个事件,当该事件执行完毕后,该事件队列的所有进程都会被放到相应的就绪队列中去。