第一节 进程调度的基本概念
进程调度即处理机调度,也叫低级调度。
在多道程序设计环境中,进程数往往多于处理机数,进程会互相争夺处理机。
进程调度的任务是控制、协调进程对CPU的竞争,按一定的调度算法,使某一就绪进程获得CPU的控制权,使其转换成运行状态。
进程调度完成的任务是将一个物理的CPU转变成多个虚拟的(或逻辑的)CPU。
进程调度程序是操作系统的真正核心,它直接负责CPU的分配。
一、进程调度的主要功能
1)保存现场:保存到PCB的现场信息去中。
2)挑选进程:调度算法(例如:优先级算法)
3)恢复现场
二、进程调度的时机
一般在以下事件发生后就要执行进程调度:
1)创建进程
2)任务完成:进程的任务已完成,但CPU时间片尚未到时,进程通过系统调用exit
通知操作系统其任务已完成;而不是傻傻地等时间片到时。
3)等待资源
4)中断发生
5)运行到时:分时系统中产生的时间中断。
三、两级调度模型
进程调度和作业调度是CPU主要的两级调度。
作业调度的任务是:完成作业从后备状态到执行状态和从执行状态到完成状态的转换。
作业调度是宏观调度,被选择的作业只是具有了获得处理机的资格。
进程调度是微观调度,根据一定的算法,把处理机动态、实际地分配给所选中的进程,使之真正地活动起来。
它们的一个基本区别是执行频率不同;进程调度相当频繁(可能每10毫秒就得调度一次)。
作业调度执行次数少,间隔可以是几分钟;它主要用来控制程序的道数;即内存中进程的数目。
某些系统中可能没有任务调度;例如分时OS中往往没有作业调度程序。
四、三级调度模式
作业调度:选一批合适的作业进入内存,并创建进程。
进程调度:从就绪队列选择合适的进程并投入运行。
中级调度:内存中驻留时间较长的进程切换到磁盘;内存足够是再放入磁盘。
第二节 进程调度算法的设计思路
一、调度策略的选择
考虑的主要因素:
1)设计目标:
批处理OS:应尽量提高各种资源的利用率和增加系统的平均吞吐率。
分时OS:保证对用户的均衡响应时间。
实时OS:必须对事件及时、可靠地处理。
网络OS:使用户和程序方便、有效地利用网络中的分布式资源。
2)公平性:
公平地对待所有作业和进程,公平共享CPU。
3)均衡性:
提高资源利用率。
4)统筹兼顾:
兼顾响应时间和资源利用率。
5)优先级:
保证优先级的同时,也要避免某些进程无限推迟。
6)开销:
开销不能太大。
实际上,往往会采用比较简单的算法,避免算法带来的额外负担。
二、性能评价标准
常用的评价标准:
(1)CPU利用率
(2)吞吐量:单位时间内完成的作业的数量。
(3)周转时间:对于一个特定的作业:作业等待进入内存的时间,进程在就绪队列中等待的时间,进程在CPU上执行和完成I/O操作所花费的时间总和。
: 作业i的提交时刻;
: 作业i的完成时刻。
带权周转时间W:
(4)就绪等待时间
(5)响应时间:从提交第一个请求到产生第一个响应所用的时间。
第三节 经典进程调度算法
一、先来先服务调度(First-Come, First-Served; FCFS)
思想:排队买票。不利于短作业。
作业调度一次课选择多个。
特点:容易实现但效率低。
二、时间片轮转调度(Round-Robin;RR)
分时OS的进程调度。
就绪队列先入先出,新进进程放入队尾;调度时选择队首进程;每个时间片通常10~100毫秒。
时间片到时则产生时间中断,未完成的进程重新放回队尾。
若时间片太长,使得每个进程都在这段时间内运行完毕,那么就退化为FCFS调度了。
若时间片太短,就会出现切换频繁的问题,使得系统开销增大。
应考虑以下内容:
1.系统响应时间
2.就绪队列进程的数目
3.进程的转换时间
4.CPU运行执行的速度;快则短,慢则长。
三、优先级调度
当进程运行时,就绪队列出现更高优先级的进程时怎么应对?
- 非抢占式:当前进程继续执行,直到完成或者因等待某事件而主动让出CPU后才重新调度。
- 抢占式:立即停止当前进程的执行,强行将CPU分派给更高优先级的进程。
优先级的指定:
- 系统内部计算:一般时动态不断变化的。
- 外部指定:一般是静态的,终身的;可能出现"饥饿"的现象。
四、最短做作业优先调度(Shortest Job First; SJF)
主要用于作业调度。
将运行时间(估计值)最短的作业放入内存;是非抢占式的;该调度算法可降低平均等待时间。
五、最短剩余时间优先调度(Shortest Remaining Time First; SRTF)
是抢占式的;当新进程加入就绪队列时,若它需要的运行时间比当前运行的进程所需的剩余时间还短,则强行夺取运行权。
六、多级队列调度(Multilevel Queue)
根据作业特点永久性地将各作业分别链接到不同队列,每个队列有自己的调度算法。
例如:将作业分为前台和后台;前台队列使用时间片轮转调度算法;后台队列使用先来先服务调度算法。
且各队列之间也需要调度,通常是采用固定优先级的抢占式的算法。
七、多级反馈队列调度(Multilevel Feedback Queue)
在MQ基础上加入"反馈"措施。
思想:设置多个就绪队列,每个队列对应一个优先级,第一个队列优先级最高,第二个次之,以此类推。
各队列进程运行的时间片也不相同,高优先级时间片小,低优先级时间片大。
新进程先插入第一个队列的队尾,被调度后且未完成则放入第二个队列的队尾,后续执行以此类推;若在最后一个队列中被调度后进程还是没有执行完成,则将此插入第一个队列的队尾,以此类推。
复杂但具有较好的性能;UNIX、Windows NT和OS/2中都采用类似算法。
第四节 其他进程调度算法
一、公平共享调度
旨在确保系统资源在多个用户或用户组之间公平分配,而不是仅在进程之间进行调度。它的设计目标是基于用户的需求,而不仅仅是进程的需求。
所有调度算法都是讲就绪的进程集合看作单一的进程池,从这个池中选择下一个要运行的进程;但是在多用户系统中,若单个用户的应用程序或作业由多个进程或者线程组成;那么传统的调度器就不认识这种进程集合结构。
从用户的角度,他关系的不是某一个特定进程如何执行而是构成应用程序的一组进程如何执行。因此,基于进程组的调度决策就十分必要;而这种调度方法通常称作公平共享调度(Fair-Share Scheduling)。
每个用户都用一个进程表示;每个用户都被指定了某种类型的权值,权值不仅定义了用户对系统资源的共享还作为所使用资源的比例。
基本思想是将总的系统资源分配到各个用户或用户组,然后再在这些用户或用户组内部对进程进行调度。具体实现可以有多种方式。
根据用户组的权重或优先级,分配资源份额。可以使用比例分配法,比如根据每个用户组的权重,将CPU时间片等资源进行分割。
在用户组内部,使用常规的进程调度算法(如轮转调度、优先级调度等)对进程进行调度。
二、保证调度
向用户做出明确的性能保证,然后去实现。
保证调度的基本思想是为每个进程分配一个权重,根据权重计算每个进程应当获得的资源份额。在调度过程中,操作系统会跟踪每个进程的实际资源使用情况,确保其获得的资源份额接近预期的保证值。
必须跟踪各个进程自创建以来已使用的CPU时间,然后计算各进程应获得的CPU时间。
保证调度是一种重要的进程调度算法,它可以确保特定进程按时完成其任务或获得其所需的资源。保证调度算法被广泛应用于各种实时系统中。
保证调度通常会牺牲其他进程的性能,因此需要谨慎使用。
三、彩票调度
是一种概率调度算法;给每个进程分发一定量的彩票,而调度器从所有彩票中随机抽一张,持有该彩票的进程获得CPU。
若需要进程获得更多的CPU时间则给它多发几张彩票。
优势:可以防止饥饿现象。(给每个进程这至少一张彩票即可。)
第五节 操作系统调度算法实例
一、BSD多级反馈队列调度
BSD UNIX主要用于分交互环境中,调度算法设计成为交互用户提供好的响应时间,又保证低优先级不会饿死。
实际上,该方法已被取代,但它是分时调度的代表,值得研究。
多级反馈队列算法中,每个优先级队列中采用轮转算法;采用1秒抢占方式,即若某个进程在1秒没有被阻塞或完成,它将被抢占。
优先级基于进程类型和执行历史计算:
1):进程j在区间i中处理器使用情况的度量。
2):进程j在区间i开始处的优先级。(值越小,优先级越高)
3):进程j的基本优先级。
4):用户可以控制的调节因子。
每秒都重新计算每个进程的优先级,并执行一次调度。
二、UNIX SVR4调度
被设计成给实时进程最高优先权,给内核模式进程次高优先权,给其他用户模式进程(分时进程)最低优先权。
引入160个优先级,划分为三类:
- 实时(159-100)进程:可以使用可抢占点,抢占内核和实时进程。
- 内核(99-60)进程
- 分时(59-0)进程
在分时进程类中,进程优先级可变,每当一个进程用完时间片,调度器会降低它的优先级;若一个进程阻塞在某个事件上,则调高其优先级。
分配给分时进程的时间量也取决于其优先级:0级100ms -> 59级50ms。
每个实时进程内中,每个进程有一个固定优先级和固定时间量。(注意这是实时进程类)
三、Linux抢占式调度
Linux下的进程可在用户态或者内核态下运行;而内核态的权限高于用户态。
进程每次执行系统调用时,会从用户态切换到内核态。
Linux系统的进程调度机制涉及:
- 调度方式:基本上采用“抢占式优先级”。
- 内核为系统中每个进程计算一个优先级;反应一个进程获得CPU的资格。
- 调度策略:
- SCHED_FIFO:短实时,自愿让出。
- SCHED_RR:较长实时,200ms时间片
- SCHED_OTHER:传统UNIX,交互分时
- 调度时机
- 使用系统调用
nanosleep()
或pause()
:主动让出CPU使用权。 - 进程终止:永久放弃CPU使用权。
- 时钟中断
- 唤醒进程
- 改变调度策略或降低自身优先级(如:修改nice值)
四、Windows调度
高度交互或作为服务器尽可能地响应单个用户需求;实现了抢占式调度器。
优先级:
- 实时类:16个优先级;线程的优先级固定不变。
- 可变类:16个优先级;有初始值,生命周期内可能随时变化。其中交互式线程往往具有最高的优先级。
是一种优先级驱动的抢占式调度器。
n个CPU的系统;n-1个高优先级进程独占n-1个CPU,其余线程共有剩余的1个CPU。
第六节 多处理器调度算法
多处理器系统:
- 松耦合分布式多处理
- 每个处理器有自己的主存和I/O通道
- 专门功能处理器
- 如I/O处理器
- 通用主处理器管理专用处理器
- 紧耦合多处理器
- 共享同一主存
- 在OS完全控制下
一、粒度
进程间的同步粒度也叫同步频率。可以根据粒度区分并行性。
1.无约束并行性(Independent Parallelism)
进程间无显式同步;典型的应用是分时OS。
2.粗粒度(Coarse)和非常粗粒度(Very Coarse)并行性
进程间存在同步,但在非常粗的粒度上。
3.中等粒度并行性
应用程序可以通过进程中的一组线程被有效地实现;由程序员显式地指定应用程序的潜在并行性。
4.细粒度并行性(Fine-grain)
比线程中的并行更复杂的情况。
二、设计问题
多处理器调度涉及:
- 将进程分配到处理器
- 静态:进程一直分配给某一个处理器;容易不平均。
- 动态:进程生命周期中可能会用到不同的处理器。
- 主从式:OS主要核心功能总在某个特定的处理器上;其他处理器用于处理用户程序。
- 对等式:OS可在任意CPU上执行,用户程序也一样;要解决不同的处理器不会同时选择相同的进程。
- 在单一处理器上使用多道程序设计
- 一个进程的实际分派:即选择哪一个进程的问题。
三、进程调度
在大多数传统的多处理器调度系统中,进程并非被指定到一个专用的处理器。
在多数多处理器系统中使用简单的FCFS原则或在静态优先级方案中使用FCFS就足够了。
四、线程调度
多处理器线程调度和处理器分配方案:
- 负载分配
- 一个就绪进程全局队列,每个CPU只要空闲就从中取进程执行。
- 最简单,但要互斥访问存储器。
- 当前使用最多。
- 组调度
- 一组相关的线程基于一对一原则,同时调度到一组?CPU上。
- 专用处理器分配
- 与负载调度正相反;每个程序分配一组CPU,CPU数与程序中线程数量相同。
- 动态调度
- 在执行期间,进程中的线程数量可变。
第七节 实时调度算法
一、实时调度算法概述
系统是否执行可调度性分析:
- 是
- 静态:执行可调度性静态分析
- 动态:执行可调度性动态分析
- 否
- 不执行可调度性分析
分类:
- 静态表驱动算法
- 静态
- 用于确定在运行时一个任务何时必须开始执行
- 静态优先级驱动抢占调度算法
- 静态
- 用于给任何任务指定优先级,使其可以使用传统的优先级驱动的抢占式调度器
- 基于动态规划调度算法
- 在运行时动态地确定可行性
- 一个任务到达,只有当能满足它的时间约束才接受
- 分析结果用于确定合适分派这个任务
- 动态尽力调度算法(商用实时系统)
- 不执行可行性分析
- 系统试图满足所有最后期限,并终止任何已经开始运行但错过最后期限的进程。
二、期限调度
大多数现代实时OS的设计目标是:尽可能快地启动实时任务,强调快速中断和任务分派。
好的调度依赖任务的:
- 就绪时间
- 启动在最后期限
- 完成最后期限
- 处理时间
- 资源需求(CPU之外的)
- 优先级
- 子任务结构
三、速率单调调度(Rate Monotonic Scheduling;RMS)
为周期性任务解决多任务调度冲突。
最短周期任务由最高优先级;任务同时执行时短周期更优先。
四、优先级反转(Priority Inversion)
在任何优先级调度方案中,系统会不停执行具有最高优先级的任务;当系统内的环境迫使一个较高优先级任务等待一个较低优先级任务时,优先级反转就发生了。
优先级反转的实例
假设系统中有三个进程:高优先级进程H、中优先级进程M和低优先级进程L。现在有如下情景:
- 低优先级进程L持有某个共享资源(如一个互斥锁)。
- 高优先级进程H需要这个共享资源,因此被阻塞,等待低优先级进程L释放资源。
- 中优先级进程M不需要这个共享资源,但由于它的优先级高于进程L,调度器会优先调度进程M运行。