调度算法
调度的基本概念: 在多道程序系统中中,进程的数量往往多于CPU的个数,因此进程竞争CPU的情况在所难免,调度是对CPU进程分配。
调度的层次: 一个作业从提交开始直到完成,往往要经历以下三级调度 1. 作业调度,又称高级调度,其主要任务是按一定的原则从外存上处于后背状态的作业中挑选一个作业,给它分配内存、输入/输出设备等必要资源,并建立相应的进程,使它获得竞争CPU的权利。 2. 中级调度,又称内存调度,其作用是提高内存利用率和系统吞吐量。 3. 进程调度,又称低级调度,其主要任务是按照某种方法和策略从就绪队列中选取一个进程,将CPU分配给它。
三级调度的联系: 作业调度从外存的后备队列中选择一批作业进入内存,为它们建立进程,这些进程被送入就绪队列,进程调度从就绪队列中选出一个进程,并把其状态改为运行态,把CPU分配给它。中级调度是为了提高内存的利用率,系统将那些暂时不能运行的进程挂起来。当内存空间宽松时,通过中级调度选择具备运行条件的进程,将其唤醒。
1、进程调度算法
进程调度算法也称CPU调度算法,毕竟进程是由CPU调度的。
在进程的生命周期中,当进程从一个运行状态到另外一个状态变化的时候,其实会触发一次调度。
硬件时钟提供某个频率的周期性中断,可以根据如何处理时钟中断把进程调度算法分类:
1. 非抢占式调度算法:一个运行进程直接运行到该进程退出(或者直到被阻塞),才会调用另外一个进程,也就是说不会理会时钟中断。 2. 抢占式调度算法:运行的进程可以被打断,使其把CPU让给其他进程。 抢占的原则一般有三种,分别是时间片原则、优先权原则、短作业优先原则。
(1)调度原则
1. CPU利用率:调度程序应确保CPU是始终匆忙的状态,这可提高CPU的利用率 2. 系统吞吐量:吞吐量表示的是单位时间内CPU完成进程的数量,长作业的进程会占用较长的CPU资源,因此会降低吞吐量; 3. 等待时间:指的是进程处于就绪队列的时间 4. 响应时间:用户提交请求到系统第一次产生响应的时间。//在交互式系统中,响应时间是衡量调度算法好坏的主要标准 //5. 周转时间。周转时间是指从作业提交到作业完成所经历的时间,是作业等待、在就绪队列中排队、在处理机上运行及进行输入/输出操作所花费时间的总和。
(2)进程调度算法
调度舒服能发是指:根据系统的资源分配策略所规定的资源分配算法。 1. 先来先服务调度算法,FCFS,First Come First Serverd 每次从就绪队列中选择最先进入的进程运行(就绪队列中存在时间最长的进程),直到进程退出或被阻塞,才会继续从队列中选择第一个进程接着运行。 //该算法既可以用于作业调度,也可以用于进程调度。 有利于长进程、CPU繁忙的进程,不利于短进程、I/O繁忙的进程; 2. 短作业优先调度算法,SJF,Shortest Job First 对预计执行时间短的进程优先分派处理机,通常后来的短进程不抢先正在执行的进程; 优点:相比于FCFS算法,SJF可以改善平均周转时间和平均带权周转时间,缩短进程的等待时间,提高系统的吞吐量, 缺点:不利于长进程,而且未能根据进程的紧迫程度来划分优先级,以及难以准确估计进程的执行时间,从而影响性能; 非抢占式算法 3. 最高优先级调度算法,HPF,Highest Priority First 调度程序能从就绪队列中选择最高优先级的进程进行运行。 * 非抢占式:当就绪队列中出现优先级高的进程,运行完当前进程,再选择优先级高的进程。 * 抢占式:当就绪队列中出现优先级高的进程,当前进程挂起,调度优先级高的进程运行。 4. 高响应比优先调度算法,HRRN,Highest Response Ratio Next 该算法是对先来先服务调度算法和短作业优先调度算法的一种综合平衡,同时考虑每个作业的等待时间和估计的运行时间。每次进行进程调度时,先计算响应比优先级,然后把响应比优先级最高的进程投入运行; 由于每次调度前都要计算响应比,系统开销相应增加。 优先权 = (等待时间 + 要求服务时间) / 要求服务时间 FCFS只考虑等待时间,SJF只考虑执行时间,而HRRN同时考虑每个作业的等待时间和执行时间 主要用于作业调度。 5. 时间片轮转调度算法,RR,Round Robin 每个进程被分配一个时间段,称为时间片(Quantum),即允许该进程组在该时间段内运行。如果时间片用完,进程还在运行,那么将会把此进程从CPU释放出来,并把CPU分配给另外一个进程。如果该进程在时间片结束前阻塞或结束,则CPU立即进行切换。 该算法适用于分时系统。 使得进程以FCFS的方式按时间片轮流使用CPU,每次调度时将CPU分派给队首进程,让其执行一个时间片,其长度从几ms到几百ms,当一个时间片结束时,发生时钟中断,调度程序据此暂停当前进程的执行,将其送到就绪队列的末尾,使其出让CPU,并通过上下文切换执行当前的队首进程;不利于处理紧急作业,而且时间片的大小对系统性能的影响很大,因此时间片的大小应适当; 6. 多级反馈队列调度算法 MFQ:Multilevel Feedback Queue 多级:表示有多个队列,每个队列优先级从高到低,同时优先级越高时间片越短。 反馈:表示如果有新的进程加入优先级高的队列时,立即停止当前正在运行的进程,转而去运行优先级高的队列。 进程在不同优先级的队列间迁移,首先调度优先级高的队列中的进程,只有优先级高的队列为空时才去调度优先级低的队列中的进程;对于同一个队列中的进程,按照时间片轮转的方式进行调度,如果N个时间片后依然未能完成,则进入优先级低的队列等待;在低优先级的队列中的进程在运行时,又有新到达的作业,那么在运行完这个时间片后,CPU分配给新到达的作业,即抢占式。
时间片的长度很重要 * 如果时间片设置过长,演变为先来先服务 * 如果时间片设置过短,导致过多的进程上下文切换,降低CPU效率。 一般来说,时间片设置为20ms~50ms。 那么应该如何确定时间片的大小? - 系统对响应时间的要求; - 就绪队列中进程的时间; - 系统的处理能力;
优先级可以分为: * 静态优先级:创建进程时候,就已经确定了优先级,然后整个运行时间优先级都不会改变。 * 动态优先级:根据进程的动态变化调整优先级。如果进程运行时间增加,则降低其优先级;如果进程等待时间(就绪队列的等待时间)增加,则升高其优先级。也就是随着时间的推移增加等待进程的优先级。
多级反馈队列调度算法工作: 1. 设置了多个队列,赋予每个队列不同的优先级,每个队列优先级从高到低,同时优先级越高时间片越短; 2. 新的进程会被放入到第一级队列的末尾,按先来先服务的原则排队等待被调度。如果在第一级队列规定的时间片没运行完成,则将其转入到第二级队列的末尾,以此类推,直至完成。 3. 当较高优先级的队列为空,才调度较低优先级的队列中的进程运行。如果进程运行时,有新进程进入较高优先级的队列,则停止当前运行的进程并将其移入到原队列末尾,接着让较高优先级的进程运行。
2、页面置换算法
(1)缺页中断(缺页异常)
在请求分页系统中,可以通过查询页表中的状态位来确定所要访问的页面是否存在于内存中。每当所要访问的页面不在内存时,会产生一次缺页中断,此时操作系统会根据页表中的外存地址在外存中找到所缺的一页,将其调入内存。 //缺页中断是由于所要访问的页面不存在于内存时,由硬件所产生的一种中断,请求操作系统将所缺页调入到内存。 缺页本身是一种中断,与一般的中断一样,需要经过4个处理步骤: 1、保护CPU现场 2、分析中断原因 3、转入缺页中断处理程序进行处理 4、恢复CPU现场,继续执行 缺页中断与一般的中断存在区别: 1、缺页中断在指令执行期间产生和处理中断信号;一般中断在一条指令执行完成后检查和处理中断信号。 2、缺页中断返回时,会重新执行导致缺页异常的这条指令;一般中断返回时,执行该指令的下一个指令。 //3、一条指令在执行期间,可能产生多次缺页中断。
缺页中断流程: 1. 在CPU里访问一条Load M指令,然后CPU会去找M所对应的页表项。 2. 如果该页表项的状态位是有效的,那CPU就可以直接去访问物理内存了;如果状态位是无效的,则CPU则会发送缺页中断请求。 3. 操作系统收到了缺页中断,则会执行缺页中断处理删除,先会查找该页面在磁盘中的页面的位置。 4. 找到磁盘中对应的页面后,需要把该页面换入到物理内存中,但是在换入前,需要在物理内存中找空闲页。如果找到空闲页,就把页面换入到物理内存中。 5. 页面从磁盘换入到物理内存完成后,则把页表项中的状态位修改为有效的。 6. 最后,CPU重新执行导致缺页异常的指令。
(2)页表项
页表项结构:
状态位:用于表示该页是否有效,也就是说是否在物理内存中,供程序访问时参考。 访问字段:用于记录该页在一段时间被访问的次数,供页面置换算法选择出页面时参考。 修改位:表示该页在调入内存后是否有被修改过,由于内存中的每一页都在磁盘上保留一份副本,因此,如果没有修改,在置换该页时就不需要将该页面写回到磁盘上,以减少系统的开销;如果已经被修改,则将该页重写到磁盘上,以保证磁盘中所保留的始终是最新的副本。 磁盘地址:用于指出该页在硬盘上的地址,通常是物理块号,供调入该页时使用。
(3)缺页调度算法
当访问一个内存中不存在的页,并且内存已满,则需要从内存中调出一个页或将数据送至磁盘对换区,替换一个页,这种现象叫做缺页置换。 缺页置换算法如下: 1. 最佳页面置换算法(OPT) 基本思路:置换在未来最长时间不访问的页面。 所以,该算法实现需要计算内存中每个逻辑页面的下一次访问时间,然后比较,选择未来最长时间不访问的页面。 这是理想的,因为现实中无法实现,无法预知之后访问哪个页面。 所以最佳页面置换算法的作用是为了衡量你的算法的效率。你的算法效率越接近该算法的效率,那么说明你的算法是高效的。 2. 先进先出置换算法(FIFO)(用的最多) 置换最先调入内存的页面,即置换在内存中驻留时间最久的页面。按照进入内存的先后次序排列成队列,从队尾进入,从队首删除。 3. 最近最久未使用置换算法(LRU) 置换最近一段时间以来最长时间未访问过的页面。根据程序局部性原理,刚被访问的页面,可能马上又要被访问;而较长时间内没有被访问的页面,可能最近不会被访问。 LRU开销大(代价高),需要在内存中维护一个所有页面的链表,最近最多使用的页面在表头,最近最少使用的页面在表尾。 4. 时钟页面置换算法(Lock) 把所有的页面都保存在一个类似钟面的环形链表中,一个表针指向最老的页面。 当发生缺页中断时,算法首先检查表针指向的页面: * 如果它访问位是0就淘汰该页面,并把新的页面插入这个位置,然后把表针前移一个位置 * 如果访问位是1就清除访问位,并把表针前移一个位置,重复这个过程直到找到了一个访问位为0的页面为止。 5. 最不常用置换算法(LFU) 当发生缺页时,淘汰访问次数最少的那个页面。 需要对每个页面设置一个访问计数器,每当一个页面被访问时,该页面的访问计数器就累加1.在发生缺页中断时,淘汰计数器值最小的那个页面。 缺点: 1. 计数器硬件成本比较高; 2. 如果要对这个计数器查找哪个页面访问次数最小,查找链表本身,如果链表长度很大,是非常耗时的,效率不高。 3. 没有考虑时间的问题,比如有些页面过去访问的频率很高,但最近很少访问;而最近经常访问的页面过去很少访问。在发生缺页中断时,会误伤最近频繁访问但次数还不高的页面。 解决方法: 可以定期减少访问的次数,比如当发生时间中断时,把过去时间访问的页面访问次数除以2。也就是说,随着时间的流失,以前的高访问次数的页面会慢慢减少,相当于加大了被置换的概率。
另一种答案:FIFO、LRU、LFU、LRU-K、2Q 1. FIFO,先进先出淘汰算法 思想:最近刚访问的,将来访问的可能性比较大 实现:使用一个队列,新加入的页面放入队尾,每次淘汰队首的页面,即先进入的数据先淘汰。 弊端:无法体现页面冷热信息 2. LFU,最不经常访问淘汰算法 思想:如果数据过去被访问多次,那么将来被访问的频率也更高 实现:每个数据块一个引用计数,所有数据块按照引用计数排序,具有相同计数的数据块则按照时间排序,每次淘汰队尾数据块 开销:排序开销 弊端:数据颠簸 3. LRU,最近最少使用替换算法 思想:如果数据最近被访问过,那么将来被访问的几率也更高 实现:使用一个栈,新页面或者命中的页面则将该页面移动到栈底,每次替换栈顶的缓存页面 优点:对热点数据命中率很高 缺点: (1)缓存颠簸 (2)缓存污染,突然大量偶发性的数据访问,会让内存中存放大量冷数据。 4. LRU-K(LRU-2,LRU-3) 思想:最久未使用K次淘汰算法 LRU-K中的K代表最近使用的次数,因此LRU可以认为是LRU-1。LRU-K的主要目的是为了解决LRU算法“缓存污染”的问题,其核心思想是将“最近使用过1次”的判断标准扩展为“最近使用过K次”。 相比LRU,LRU-K需要多维护一个队列,用于记录所有缓存数据被访问的历史。只有当数据的访问次数达到K次的时候,才将数据放入缓存。当需要淘汰数据时,LRU-K会淘汰第K次访问时间距当前时间最大的数据。 实现: 1)数据第一次被访问,加入到访问历史列表; 2)如果数据在访问历史列表里后没有达到 K 次访问,则按照一定规则(FIFO,LRU)淘汰; 3)当访问历史队列中的数据访问次数达到 K 次后,将数据索引从历史队列删除,将数据移到缓存队列中,并缓存此数据,缓存队列重新按照时间排序; 4)缓存数据队列中被再次访问后,重新排序; 5)需要淘汰数据时,淘汰缓存队列中排在末尾的数据,即:淘汰“倒数第 K 次访问离现在最久”的数据。 针对问题:LRU-K的主要目的是为了解决LRU算法“缓存污染”的问题,其核心思想是将“最近使用过1 次”的判断标准扩展为“最近使用过K次” 5、2Q 类似LRU-2。使用一个FIFO队列和一个LRU队列。 实现: 1)新访问的数据插入到 FIFO 队列; 2)如果数据在 FIFO 队列中一直没有被再次访问,则最终按照 FIFO 规则淘汰; 3)如果数据在 FIFO 队列中被再次访问,则将数据移到 LRU 队列头部; 4)如果数据在 LRU 队列再次被访问,则将数据移到 LRU 队列头部; 5)LRU 队列淘汰末尾的数据。 针对问题:LRU 的缓存污染 弊端:当FIFO容量为2时,访问负载是:ABCABCABC会退化为FIFO,用不到LRU
1.最佳置换算法:
2.先进先出置换算法
3.最近最久未使用置换算法
4.时钟页面置换算法
3、磁盘调用算法
1. 先来先服务算法,First Come First Served,FCFS 2. 最短寻道时间优先算法,Shortest Seek First,SSF 优先选择从当前磁头位置所需寻道时间最短的请求。该算法可能造成某些请求的饥饿,原因是磁头在一小块区域来回移动。 3. 扫描算法,Scan 磁头在一个方向上移动,访问所有未完成的请求,直到磁头到达该方向上的最后的磁道,才调换方向。 该算法性能较好,不会产生饥饿,但是中间部分的磁道会比较占便宜,中间部分相比其他部分响应的频率会比较高,也就是说每个磁道的响应频率存在差异。 4. 循环扫描算法,Circular Scan,CSCAN 只有磁头朝某个特定方向移动时,才处理磁道访问请求,而返回时直接快速移动至最靠边缘的磁道,也就是复位磁头,这个过程是很快的,并且返回中途不处理任何请求,该算法的特点,就是磁道只响应一个方向上的请求。 循环扫描算法相比于扫描算法,对于各个位置磁道响应频率相对比较平均。 5. LOOK与C-LOOK算法 优化思路是磁头在移动到最远的请求位置,然后立即方向移动。 SCAN基础上优化叫LOOK CSCAN基础上优化叫C-LOOK
1. 先来先服务
2. 最短寻道时间优先算法
3. 扫描算法
4. 循环扫描算法