一文详解操作系统进程管理( 二 )


阻塞 -> 就绪:当等待结束了,就由阻塞态进入就绪态 。
运行 -> 终止:当进程表示自己已经完成了,它会被操作系统终止 。
这便是对于单个进程,经典的五状态模型 。当存在多个进程时,由于同一时间只能有一个进程在执行,那么如何去管理这一系列的处于阻塞态和就绪态的进程呢?一般来说,会使用就绪队列,和阻塞队列,让处于阻塞态和就绪态的进程进入队列,排队执行 。下图是一个单一阻塞队列模型 。

一文详解操作系统进程管理

文章插图
 
基于此,还可以扩展出多个就绪队列,每个优先级对应一个队列,这样子操作系统在选择要调度哪一个进程时,可以有更大的灵活性 。下面将进一步探讨队列与进程之间如何组织管理 。也可以有多条阻塞队列,每一个事件对应一个阻塞队列,当事件发生时,该队列所有进程都进入就绪态 。
2.2.2 七状态模型上面所讲的进程状态存在一个前提:每个进程都必须完全载入内存 。一旦排队的进程多了,对于有限的内存空间将会是极大的考验 。为了解决内存占用问题,可以将一部分内存中的进程交换到磁盘中,这些被交换到磁盘的进程,会进入挂起状态,进一步还可细分为就绪/挂起,阻塞/挂起 。对于单个进程的状态转换如下图 。
一文详解操作系统进程管理

文章插图
 
整体上对于挂起队列的转换关系,如下图 。
一文详解操作系统进程管理

文章插图
 
关于图中的几种调度,将会在下面第4章进一步描述 。
2.2.3 进程切换当一个正在运行中的进程被中断,操作系统指定另一个就绪态的进程进入运行态,这个过程就是进程切换,也可以叫上下文切换 。
该切换过程一般涉及以下步骤:
1.保存处理器上下文环境:将CPU程序计数器和寄存器的值保存到当前进程的私有堆栈里
2.更新当前进程的PCB(包括状态更变)
3.将当前进程移到就绪队列或者阻塞队列
4.根据调度算法,选择就绪队列中一个合适的新进程,将其更改为运行态
5.更新内存管理的数据结构
6.新进程内对堆栈所保存的上下文信息载入到CPU的寄存器和程序计数器,占有CPU
2.3 进程组织每一个PCB表示一个进程,多个进程同时存在时,需要一定的方式将这些PCB组织起来,便于操作系统访问 。常见的组织方式有如下3种 。
2.3.1 线性表
一文详解操作系统进程管理

文章插图
 
所有的PCB存放于一张线性表中,每次查找时需要遍历线性表 。比较适用于进程数量不多的情况,如果有几百上千个进程,每次操作都进行遍历,那将是十分耗时的 。
2.3.2 链表 
一文详解操作系统进程管理

文章插图
 
上面提到的就绪队列和阻塞队列,他们可以以链表的形式组织 。从图中可以看出就绪队列指向PCB1,PCB1右边的数字“2”表示链表指向的下一个节点PCB2 。依此类推,PBC以如下链表形式串联起来 。
执行指针 -> PCB4就绪队列指针 -> PCB1 -> PCB2 -> PCB3 -> PCB5阻塞队列指针 -> PCB7 -> PCB8 -> PCB6优点:非常直观,进程调度查找起来方便 。
缺点:查找的时候需要从链表的头部开始进行遍历 。如果进程状态发生变化,那么链表中进程节点的指针指向需要发生变动 。
2.3.3 索引
一文详解操作系统进程管理

文章插图
 
优点:基于链表的方式进行进一步的优化,通过索引查找进程,可以将查找的时间复杂度由O(n)优化到O(1) 。如果进程状态发生变化,只需要操作索引表,相比于操作整个链表更便捷 。
缺点:建立了索引表,需要额外的内存空间 。相当于是利用空间去换取时间 。
3. 线程3.1 线程结构基于前面所描述,进程包含了两大特点:
1. 资源所有权:进程是一个容器,聚集了内存,I/O 设备,文件等资源,拥有这些资源的控制或所有权 。
2. 调度/执行:具有执行状态(运行,就绪,阻塞等),可被操作系统的调度程序所调度 。
早期的操作系统中,一般一个进程内只有一个线程,即为单线程进程模型 。如下图,其中所包含的用户栈和内核栈,用于管理调度和返回的行为 。当进程不运行的时候,CPU的寄存器中的内容将被保存起来,以便于下一次运行该进程时,恢复当时的状态 。


推荐阅读