目录
- 调度策略相关概念
- 调度指标
- 批处理系统调度算法
- 1. 先来先服务(First Come First Served, FCFS)
- 2.短作业优先(Short Job First, SJF)
- 3.最短剩余时间优先(Shortest Remaining Time Next, SRTN)
- 4. 最高响应比优先(Highest Response Ratio Next, HRRN)
- 交互式系统调度算法
- 1. 时间片轮转(Round Robin, RR)
- 2. 最高优先级调度算法(Highest Priority First, HPF)
- 3. 多级反馈队列调度算法(Multi-Level Feedback Queue, MLFQ)
- 公平分享调度算法
- *多处理机调度算法
- 1. 硬件支持及软件机制
- 2. 单队列调度((Single Queue Multiprocessor Scheduling,SQMS)
- 3. 多队列调度((Multi-Queue Multiprocessor Scheduling,MQMS)
CPU虚拟化包括微观和宏观两个方面,微观层面是实现进程切换的机制(
),宏观层面是进程调度的策略(
)。
调度策略相关概念
1.进程优先级
静态优先级:进程创建时确定,运行过程中不再改变。
动态优先级:进程创建时指定优先级,运行过程中可以动态变化。
2.进程就绪队列组织
内存中开辟多个就绪队列,队列的优先级从上至下依次降低,CPU按照队列的优先级调度运行进程,当前队列无进程时,CPU才会调度次优先级队列内进程。
3.抢占与非抢占
可抢占式:当有比正在运行的进程优先级更高的进程就绪时,系统可强行剥夺当前运行进程的CPU使用权,提供给更高优先级的进程使用。
不可抢占式:某一进程被调度运行后,除非自身原因导致不能运行,否则一直运行下去。
4.I/O密集型和CPU密集型进程
I/O密集型:需要频繁地进行I/O操作的进程。
CPU密集型:需要大量的CPU时间进行计算。
5.时间片
时间片是允许进程在CPU运行的时间长度。
调度指标
- 周转时间(Turnaround Time):每个进程从提出请求到运行完成的时间。
带权周转时间(Turnaround Time With Weight):周转时间与实际运行时间的比值。
等待时间(Waiting time):进程处于等待CPU调度的时间之和。 - 响应时间(Response Time):从提出请求到第一次回应的时间。
- 公平性(Fairness):保证每个进程都能获得一定程度的CPU时间。
除此之外,CPU的调度指标还包括吞吐量(Throughput)、CPU利用率(CPU Utilization)之类的指标。
批处理系统调度算法
1. 先来先服务(First Come First Served, FCFS)
先来先服务(FCFS)调度算法利用队列的先进先出特性调度进程,按照进程就绪的先后顺序使用CPU,属于非抢占式调度算法。
优缺点:
(1) 简单+效率低:可以不需修改直接使用队列数据结构,但FCFS的平均周转时间一般相比其他调度算法更长。
(2) 有利于长作业+不利于短作业:长作业会长时间运行在CPU上,而短作业如果排在长作业之后,需要等待长作业完成,其周转时间必然会很长。
(3) 有利于CPU密集型+不利于I/O密集型:CPU密集型很少有I/O操作,一旦获得CPU就会长时间占用,而I/O密集型需要频繁访问IO端口,每次访问都要放弃CPU,等I/O访问完后就排在就绪队列队尾,所以要等待很久才能重新被调度。
2.短作业优先(Short Job First, SJF)
短作业优先(SJF)执行内存中运行时间最短的进程,属于非抢占式调度算法。
优缺点:
(1) 有利于短作业+不利于长作业:SJF优先调度运行时间短的进程,短作业的周转时间减少,长作业的周转时间增加,甚至会导致长作业出现“饥饿”现象。
(2) 最短平均周转时间和等待时间+未考虑作业的紧迫程度、作业时间仅为用户估计
3.最短剩余时间优先(Shortest Remaining Time Next, SRTN)
最短剩余时间优先(SRTN)是SJF的抢占式版本,即当一个新就绪的进程比当前运行的进程具有更短的完成时间时,系统剥夺当前进程的CPU使用权,运行新就绪的进程。
4. 最高响应比优先(Highest Response Ratio Next, HRRN)
最高响应比优先(HRRN)是对FCFS和SJF的综合平衡,调度时计算每个进程的响应比 ,总是选择
优点:
(1) 当等待时间相同时,则运行时间越短响应比越高,实现短作业优先(SJF)
(2) 当运行时间相同时,响应比由等待时间决定,等待时间越长响应比越高,实现先来先服务(FCFS)
(3) 长作业的响应比随着等待时间的增加而提高,从而能够及时地得到处理,克服“饥饿”状态
例题:
假设系统中有4个作业,它们的提交时间分别是8、8.4、8.8、9,运行时间依次是2、1、0.5、0.2,系统采用FCFS、SJF、HRRN和SRTN调度算法,求这组作业的等待时间、周转时间和带权周转时间。
答:FCFS、SJF、HRRN均为非抢占式调度算法,所以调度算法会在作业1执行完毕后发挥作用。作业1的提交时间为8,运行时间为2。因为作业1最先到达就绪队列,此时作业1运行时间最短,开始时间为8,等待时间为0,完开始时间为8,等待时间为0,完成时间为10(开始时间+运行时间),周转时间为2(完成时间-提交时间),带权周转时间为1(周转时间/运行时间)。
FCFS:作业1运行完毕后,此时内存中还有作业2、3、4,其中作业2最先到达,所以CPU运行作业2,之后是作业3和作业4。
作业号 | 提交时间 | 运行时间 | 开始时间 | 等待时间 | 完成时间 | 周转时间 | 带权周转时间 |
1 | 8 | 2 | 8 | 0 | 10 | 2 | 1 |
2 | 8.4 | 1 | 10 | 1.6 | 11 | 2.6 | 2.6 |
3 | 8.8 | 0.5 | 11 | 2.2 | 11.5 | 2.7 | 5.4 |
4 | 9 | 0.2 | 11.5 | 2.5 | 11.7 | 2.7 | 13.5 |
SJF:作业1运行完毕后,此时内存中还有作业2、3、4,其中作业4的运行时间最短被调度,之后是作业3和作业2。
作业号 | 提交时间 | 运行时间 | 开始时间 | 等待时间 | 完成时间 | 周转时间 | 带权周转时间 |
1 | 8 | 2 | 8 | 0 | 10 | 2 | 1 |
2 | 8.4 | 1 | 10.7 | 2.3 | 11.7 | 3.3 | 3.3 |
3 | 8.8 | 0.5 | 10.2 | 1.4 | 10.7 | 1.9 | 3.8 |
4 | 9 | 0.2 | 10 | 1 | 10.2 | 1.2 | 6 |
HRRN:作业1运行完毕后,此时内存中还有作业2、3、4,各自的响应比为1.8、3.4、6,作业4的响应比最高被选择调度运行,其次是作业3和作业2,该作业序列的HRRN调度顺序与SJF的调度顺序相同,结果也相同。
SRTN:作业1的提交时间为8,运行时间为2。因为作业1最先到达就绪队列,此时作业1剩余运行时间时间最短,开始时间为8,等待时间为0,运行至8.4,作业2 进入内存,此时作业1剩余时间为1.6,作业2剩余时间为0.5,CPU调度运行作业2,其他同理直至运行完毕。
作业号 | 提交时间 | 运行时间 | 开始时间 | 等待时间 | 完成时间 | 周转时间 | 带权周转时间 |
1 | 8 | 2 | 8 | 1.7 | 11.7 | 3.7 | 1.85 |
2 | 8.4 | 1 | 8.4 | 0.7 | 10.1 | 1.7 | 1.7 |
3 | 8.8 | 0.5 | 8.8 | 0.2 | 10.7 | 1.9 | 3.8 |
4 | 9 | 0.2 | 9 | 0 | 9.2 | 0.2 | 1 |
交互式系统调度算法
1. 时间片轮转(Round Robin, RR)
时间片轮转算法(RR)通过时分复用将cpu时间划分为固定大小的时间片(time slice),每个进程在CPU运行一个时间片,时间片一到便切换运行到下一程序,属于抢占式调度算法。
RR算法的时间片大小对性能影响很大,如果时间片太长,以至于所有进程都能在一个时间片内执行完毕,则RR算法退化成为FCFS算法;如果时间片太短,CPU将在进程间频繁切换,从而浪费CPU时间。
优缺点:
(1) 公平、有利于交互式计算
(2) 进程切换浪费CPU时间
2. 最高优先级调度算法(Highest Priority First, HPF)
最高优先级算法(HPF)总是选择优先级最高的进程运行,可以用一个数(优先数)来表示进程优先级,通常情况下:
- 系统进程优先级高于用户进程;
- 前台进程优先级高于后台进程;
- 操作系统更偏好于IO型进程。
优先级可以是静态的也可以是动态的,根据优先级数确定
优缺点:实现简单;不公平
3. 多级反馈队列调度算法(Multi-Level Feedback Queue, MLFQ)
多级反馈队列算法(MLFQ)是RR算法和HPF算法的综合平衡,动态调整进程的优先级和时间片大小,实现思想如下:
(1) 设置多个就绪队列,并为每个队列赋予不同的优先级,第 1 级队列的优先级最高,第 2 级队列次之,其余队列的优先级逐次降低; 赋予各个队列中各个进程执行时间片的大小也不相同,优先级越高的队列,每个进程的运行时间片越小。
(2) 当一个新进程进入内存后,首先放入第 1 级队列的末尾,按 FCFS 的原则排队等待调度。当该进程执行时,如果其能在时间片内完成便撤离系统;如果它在一个时间片结束未完成,该进程进入第 2 级队列按照FCFS 的原则等待调度,以此类推。直到最后一级队列,进程执行一个时间片结束未完成会回到该队列的队尾。
(3) 仅当第 1 级队列为空时,调度程序才调度第 2 级队列的进程进行执行,以此类推。
优点:
(1) 短批处理作业可以在前面的队列内完成,长批处理作业可以得到部分执行。
(2) 交互型作业通常较短,系统只要能使其第1级队列所规定的时间片内完成,即可使终端用户感到满意。
(3) 不必人为估计进程的执行时间。
例题:
假设系统中有3个反馈队列Q1,Q2,Q3,时间片分别为2,4,8。 现在有3个进程P1,P2,P3分别在时间 0 ,1,3时刻到达。而它们所需要的CPU时间分别是3,2,1个时间片。
答:
- 时刻0: P1到达。进入到队列1 , 运行1个时间片 , 时间片还未到,此时P2到达。
- 时刻1: P2到达。 进入到队列1,此时时间片仍然由P1掌控,于是P2等待。
- 时刻2: P1再运行了1个时间片后,已经完成了在Q1中的2个时间片的限制。P1被至于Q2等待被调度,CPU分配给P2。
- 时刻3: P3到达,此时时间片仍然由P2掌控,故P3在Q1等待调度,P1也在Q2等待调度。
- 时刻4: P2处理完成,由于P3,P1都在等待调度,但是P3所在的队列比P1所在的队列的优先级要高,于是P3被调度,P1继续在Q2等待。
- 时刻5: P3经过1个时间片,完成。
- 时刻6: 由于Q1已经空闲,于是开始调度Q2中的作业,则P1得到处理器开始运行。 P1再经过一个时间片,完成了任务。于是整个调度过程结束。
公平分享调度算法
时间片轮转算法可以实现部分公平,让每个进程都能使用CPU,但越晚来到达的进程需要等待的时间越长,下面介绍公平分享调度算法之一的彩票调度算法(lottery scheduling)。
彩票调度算法使用 彩票(ticket) 作为分配CPU使用权的依据:每个进程持有一定份额的彩票,系统调度进程前使用 随机数字生成器(random number generator) 抽取号码,被抽中的进程获得CPU的使用权。假设共有100张彩票,进程 A 拥有 ~ 号 和进程 B 持有 ~ 号,各占 % 和 %。
系统抽取号码:
进程执行情况:
彩票机制还会涉及到以下概念:
- 彩票面值(ticket currency):假设用户 和用户 各自获得 张彩票,用户 超发货币,向自己的进程分配 张彩票,用户 向自己的进程只分配 张彩票,但系统调度时 张用户 的彩票只相当于用户
- 彩票转让(ticket transfer):在C/S模式架构中,客户可以将自己的彩票暂时转让给服务器,让服务器尽可能多地使用CPU,从而加快为客户机提供请求的内容。
- 彩票膨胀(ticket inflation):在协作式操作系统中,用户可以提高进程持有的彩票数目,从而加快紧急程度高的进程执行。区别于彩票面值,彩票膨胀适用于单个用户的进程间抢夺CPU使用权。
除了彩票调度算法,公平分享调度算法还包括步幅调度(stride scheduling)、完全公平调度算法(CFS),THU的uCore实验中会包括两者的实现,到时候再来完善。
*多处理机调度算法
多处理器(multiprocessor)系统逐渐从高端服务器扩散到个人PC、笔记本电脑甚至移动设备上。多处理器极大提高计算机的运算性能,又不增加太多功耗,但同时也带来了一些困难:
- 典型的应用程序(例如你写的很多C程序)都只使用一个CPU,增加了更多的CPU并没有让这类程序运行得更快。为解决这个问题,需要重写应用程序引入多线程(thread),使之能够并行(parallel)工作,这在后面的章节会详细阐述。
- 其次,我们已经讨论过单处理机的进程调度,而面对多处理机时时,进程又该如何调度呢? 这正是我们以下需要阐明的。不过,按照惯例依然先说明多处理机调度需要的硬件和机制支持,再阐明具体的进程调度策略。
1. 硬件支持及软件机制
缓存是基于的局部性(locality)的概念,使用缓存能极大提高数据的处理效率,而局部性包括时间局部性和空间局部性。
- 硬件缓存(hardware cache):介于中央处理器和主存储器之间的高速小容量存储器,保存内存中最常访问的数据备份。相比之下,内存很大且拥有所有的数据,但访问速度较慢。
- 时间局部性(temporal locality):当一个数据被访问后,它很有可能会在不久的将来被再次访问,比如循环代码中的数据或指令本身。
- 空间局部性(spatial locality):当程序访问地址为x的数据时,很有可能会紧接着访问x周围的数据,比如遍历数组或指令的顺序执行。
多处理机和单处理机的区别在于对硬件缓存(cache)的使用,以及多处理器之间共享数据的方式。
- 缓存一致性(cache coherence):通过监控内存访问保证多个缓存之间共享数据的一致。每个缓存都通过监听链接所有缓存和内存的总线,如果CPU发现对它放在缓存中的数据更新,则会作废本地副本,并修改为新值。
- 缓存亲和度(cache affinity):进程在某个CPU上运行时,会在该CPU的缓存中维护许多状态。下次该进程在相同CPU上运行时,由于缓存中的数据而执行得更快。相反,在不同的CPU上执行,由于缓存一致性而不会执行出错,但需要重新加载数据而很慢。
同时,软件需要使用互斥原语(比如锁),才能保证共享数据或数据结构的正确性。假设多CPU并发访问一个共享队列,不使用互斥原语,并发地从队列增加或删除元素,缓存一致性所保存的共享数据并非预期结果。
2. 单队列调度((Single Queue Multiprocessor Scheduling,SQMS)
最基本的方式是简单地复用单处理器调度的基本架构,将所有需要调度的工作放入一个单独的队列中,称为单队列多处理器调度(Single Queue Multiprocessor Scheduling,SQMS)。
SQMS的优点是从单CPU调度程序很简单地发展,缺点则是扩展性不好,而且不能很好地保证缓存亲和度。
- 首先,缺乏可扩展性(scalability)。为了保证在多CPU上正常运行,调度程序的开发者需要在每个进程代码中通过加锁(locking)来保证原子性。但随着系统中的CPU数增加时,系统花费了越来越多的时间在锁的开销上。
- 其次,SQMS不利于缓存亲和性。比如,假设我们有5个工作(A、B、C、D、E)和4个处理器,4个CPU一次性执行A-D工作一个时间片,然后切换E-C,如此循环执行,可以看出每个工作都不断在不同CPU之间转移,缓存亲和性得不到体现,现象反而与内存抖动类似。
3. 多队列调度((Multi-Queue Multiprocessor Scheduling,MQMS)
多队列多处理器调度(Multi-Queue Multiprocessor Scheduling,MQMS)包含多个调度队列,每个队列可以使用不同的调度规则,比如轮转或其他任何可能的算法。
假设系统中有两个CPU(CPU 0和CPU 1),调度队列Q0和Q1均采用RR策略,调度运行结果如下:
MQMS相比SQMS有具有可扩展性。队列的数量会随着CPU的增加而增加,因此锁和缓存争用的开销不是大问题。此外,MQMS天生具有良好的缓存亲和度。所有工作都保持在固定的CPU上,因而可以很好地利用缓存数据。但是,如果作业分配不当,MQMS也有负载不均(load imbalance)的问题。比如,CPU0不分配作业,那么CPU0会一直空闲,而CPU1会一直忙碌。
解决措施就是采用工作窃取(work stealing)的技术。通过这种方法,工作量较少的源队列不定期地“偷看”其他目标队列是不是比自己的工作多。如果目标队列比源队列更满,就从目标队列“窃取”一个或多个工作,实现负载均衡。