CPU调度

CPU调度是多道程序操作系统的基础。通过在进程之间切换CPU,操作系统可以提高计算机的吞吐率。

进程调度—线程调度

基础
当一个进程必须等待时,操作系统会从该进程拿走CPU的使用权,而将CPU交给其他进程。
CPU的成功调度依赖于进程的如下属性:进程执行由CPU执行和I/O等待周期组成。进程在这两个状态之间切换。CPU burst—I/O bust
I/O约束程序通常具有很多短CPU区间。CPU约束程序可能有少量的长CPU区间。

CPU程序调度
每当CPU空闲时,操作系统就必须从就绪队列中选择一个进程来执行。进程选择由短期调度程序(short-term scheduler)或CPU调度程序执行。调度程序从内存中选择一个能够执行的进程,并为之分配CPU。
就绪队列不必是先进先出(FIFO)队列,也可为优先队列、树或简单的无序链表。队列中的记录通常为进程控制块(PCB)。
抢占调度:
CPU调度决策可在如下4种情况环境下发生:
(1)当一个进程从运行切换到等待状态
(2)当一个进程从运行状态切换到就绪状态
(3)当一个进程从等待状态切换到就绪状态
(4)当一个进程终止时
对于第1和4两种情况,没有选择而只有调度。
当调度只能发生在第1和4两种情况下时,称调度方案是非抢占的(nonpreemptive)或协作的(cooperative);否则,称调度方案为抢占的(preemptive)。采用非抢占调度,一旦CPU分配给一个进程,那么该进程会一直使用CPU直到进程终止或切换到等待状态。抢占调度对方问共享数据是由代价(如加锁)的,需要新的机制来协调对共享数据的访问。
抢占对于操作系统内核的设计也有影响。在处理系统调用时,内核可能忙于进程活动。这些活动可能涉及要改变重要内核数据。
因为根据定义中断能随时发生,而且不能总是被内核所忽视,所以受中断影响的代码段必须加以保护以避免同时访问。操作系统需要在任何时候都能够接收中断,否则输入会丢失或输出会被改写。为了这些代码段不被多个进程同时访问,在进入时就要禁止中断,而在退出时要重新允许中断。
分派程序(dispatch):是一个模块,用来将CPU的控制交给由短期调度程序选择的进程。
其功能包括:切换上下文、切换到用户模式、跳转到用户程序的合适位置,以重新启动程序。分派程序停止一个进程而启动另一个所花的时间成为分派延迟(dispatch latency)。

调度准则
包括:CPU使用率、吞吐量(指一个时间单元内所完成进程的数量)、周转时间(从进程提交到进程完成的时间段,是所有时间段之和,包括等待进入内存、在就绪队列中等待、在CPU上执行和I/O执行)、等待时间(在就绪队列中等待所花费时间之和)、响应时间(从提交请求到产生第一响应的时间)。
需要使CPU使用率和吞吐量最大化,而是周转时间、等待时间和响应时间最小化。有时需要优化最大值或最小值,而不是平均值。

调度算法
(1)先到先服务(First-Come,First-Served scheduling):先请求CPU的进程先分配到CPU。FCFS策略可以用FIFO队列来容易实现。当一个进程进入就绪队列,其PCB链接到队列的尾部。当CPU空闲时,CPU分配给位于队列头的进程,接着运行进程从队列中删除。不过采用FCFS策略的平均等待时间通常比较长。当进程CPU区间时间变化很大,平均等待时间会变化很大。
假设有一个CPU约束进程和许多I/O约束进程,CPU约束进程会移回到就绪队列并被分配到CPU。再次所有I/O进程会在就绪队列中等待CPU进程的完成。由于所有其他进程都等待一个大进程释放CPU,这称之为护航效果(convoy effect)。与让较短进程最先执行相比,这样会导致CPU和设备使用率变的很低。
FCFS调度算法是非抢占的。对于分时系统(每个用户需要定时的等待一定的CPU时间)是特别麻烦。允许一个进程保持CPU时间过长是个严重错误。
(2)最短作业优先调度(shortest-job-first scheduling,SJF):将每个进程与下一个CPU区间段相关联。当CPU为空闲时,它会赋给具有最短CPU区间的进程。如果两个进程具有同样长度,那么可以使用FCFS调度来处理。注意,一个更为适当地表示是最短下一个CPU区间的算法,这是因为调度检查进程的下一个CPU区间的长度,而不是其总长度。
SJF算法的平均等待时间最小。SJF算法的真正困难是如何知道下一个CPU区间的长度。对于批处理系统的长期(作业)调度,可以将用户提交作业时间所制定的进程时间极限作为长度。SJF调度经常用于长期调度。
它不能在短期CPU调度层次上加以实现。我们可以预测下一个CPU区间。认为下一个CPU区间的长度与以前的相似。因此通过计算下一个CPU区间长度的近似值,能选择具有最短预测CPU区间的进程来运行。下一个CPU区间通常可预测为以前CPU去剪的测量长度的指数平均(exponential average)。
SJF算法可能是抢占的或非抢占的。抢占SJF算法可抢占当前运行的进程,而非抢占的SJF算法会允许当前的进程先完成其CPU区间。抢占SJF调度有时称为最短剩余时间优先调度(shortest-remaining-time-first scheduling)。
(3)优先级调度(priority scheduling algorithm):  SJF算法可作为通用的优先级调度算法的一个特例。每个进程都有一个优先级与其关联,具有最高优先级的进程会分配到CPU。具有相同优先级的进程按FCFS顺序调度。SJF,其优先级(p)为下一个CPU区间的倒数。CPU区间越大,则优先级越小,反之亦然。
高优先级—低优先级 0为最高优先级或最低优先级,这里假设数字小,优先级高。
优先级可通过内部或外部方式来定义。内部定义优先级使用一些测量数据以计算进程优先级。外部优先级是通过操作系统之外的准则来定义,如进程重要性等。
优先级调度可以使抢占的或非抢占的。
优先级调度算法的一个重要问题是无求阻塞(indefinite blocking)或饥饿(starvation)。可以运行但缺乏CPU的进程可认为是阻塞的,它在等待CPU。优先级调度算法会使某个有低优先级无穷等待CPU。
低优先级进程务求等待问题的解决之一是老化(aging)。老化是一种技术,已逐渐增加在系统中等待很长时间的进程的优先级。
(4)轮转法调度(round-robin,RR):专门为分时系统设计。它类似于FCFS调度,但是增加了抢占以切换进程。定义一个较小的时间单元,称为时间片(time quantum,or time slice)。将就绪队列作为循环队列。CPU调度程序循环就绪队列,为每个进程分配不超过一个时间片段的CPU。
新进程增加到就绪队列的尾部。CPU调度程序从就绪队列中选择第一个进程,设置定时器在一个时间片之后中断,再分派该进程。接下来将可能发生两种情况。进程可能只需要小于时间片的CPU区间。对于这种情况,进程本身会自动释放CPU。调度程序接着处理就绪队列的下一个进程。否则,如果当前运行进程的CPU区间比时间片要长,定时器会中断产生操作系统中断,然后进行上下文切换,将进程加入到就绪队列的尾部,接着CPU调度程序会选择就绪队列中的下一个进程。
如果就绪队列中有n个进程且时间片为q,那么每个进程会得到1/n的CPU时间,其长度不超过q时间单元。每个进程必须等待CPU时间不会超过(n-1)q个时间单元,直到它的下一个时间片为止。
RR算法的性能很大程度上依赖于时间片的大小。在极端情况下,如果时间片非常大,那么RR算法与FCFS算法一样。如果时间片很小,那么RR算法成为处理器共享,n个进程对于用户都有它自己的处理器,速度为真正处理器速度的1/n。
希望时间片比上下文切换时间长。
周转时间也依赖于时间片的大小。
(5)多级队列调度(Multilevel Queue Scheduling):前台(交互)进程和后台(批处理)进程。这两种不同各类型的进程具有不同响应时间要求,也有不同调度需要。与后台进程相比,前台进程要有更高(或外部定义)的优先级。
多级队列调度算法将就绪队列分成多个独立队列。根据进程的属性,如内存大小等,一个进程被永久地分配到一个队列,每个队列有自己的调度算法。前台队列可能采用RR算法调度,而后台调度可能采用FCFS算法调度。
另外,队列之间必须有调度,通常采用固定优先级抢占调度。另一种可能在队列之间划分时间片。
(6)多级反馈队列调度(Multilevel Feedback-Queue Scheduling):允许进程在队列之间移动。主要思想是根据不同CPU区间的特点以区分进程。如果进程使用过多CPU时间,那么它可能被转移到较低优先级队列。这种方案将I/O约束和交互进程留在更高优先级队列。此外,在较低优先级队列中等待时间过长的进程会被转移到更高优先级队列。这种形式的老化组织饥饿的发生。
通常,多级反馈队列调度程序可由下列参数来定义:队列数量、每个队列的调度算法、用以确定何时升级到更高优先级队列的方法、用以确定何时降级到更低优先级队列的方法、用以确定进程在需要服务时应进入哪个队列的方法。

多处理器调度(Multiple-Processor Scheduling):如果多个CPU,则负载分配(load sharing)。其中主要讨论处理器功能相同(或同构)的系统,可以将任何处理器用于运行队列内的任何进程。
多处理器调度方法:在一个多处理器中,CPU调度的一种方法是让一个处理器(主服务器)处理所有的调度决定、I/O处理以及其他系统活动,其他的处理器只执行用户代码。这种非对称处理(asymmetric multiprocessing)方法更为简单,因为只有一个处理器访问系统数据结构,减轻了数据共享的需要。另一种方法是使用对称多处理(symmetric multiprocessing,SMP)方法,即每个处理器自我调度。所有进程可能处于一个共同的就绪队列中,或每个处理器都有自己的私有就绪队列。无论如何,调度通过每个处理器检查共同就绪队列并选择一个进程来执行。如果多个处理器试图访问和更新一个共同数据结构,那么每个处理器必须仔编程:必须确保两个处理器不能选择同一进程,且进程不会从队列中丢失。
处理器亲和性:进程移到其他处理器上时,被迁移的第一个处理器的缓存中的内容必须为无效,而将要迁移的第二个处理器上的缓存需重新构建。由于使缓存无效或重构的代价高,因而SMP努力的使一个进程在同一个处理器上运行,这被称为处理器亲和性,即一个进程需有一种对其他运行所在的处理器的亲和性。软亲和性(soft affinity,操作系统具有设法让一个进程保持在同一个处理器上运行的策略,但不能做任何保证)—硬亲和性(hard affinity,允许进程指定它不允许移至其他处理器)。
负载平衡(load balancing):设法将工作负载平均地分配到SMP系统中的所有处理器上。通常只是对那些拥有自己私有的可执行的进程的处理器而言是必要的。两种方法:push migration(一个特定的任务周期性地检查每个处理器上的负载,如果发现不平衡,即通过将进程从超载处理器移到(或推送到)空闲或不太忙的处理器,从而平均地分配负载,当空闲处理器从一个忙的处理器上推送pull一个等待任务时,发生pull migration)和pull migration。会抵消处理器亲和性。达到限额。
对称多线程:提供多个逻辑(而非物理的)处理器来运行几个线程,称为对称多线程(SMT),或超线程(hyperthreading)技术。即使系统仅有单处理器,每个逻辑处理器都有它自己的架构状态,包括通用目的和机器状态寄存器。每个逻辑处理器负责自己的中断处理,这意味着中断被送到并被逻辑处理器所处理,每个逻辑处理器共享其物理处理器的资源,如缓存或总线。SMT是硬件而非软件提供的。硬件应该提供每个逻辑处理器的架构状态的表示以及中断处理方法。调度程序首先设法把不同线程分别调度到每个物理处理器上,而不是调度到同一个物理处理器的不同逻辑处理器上。

线程调度:用户线程---内核线程
系统调度的是内核线程,而不是进程。用户线程由线程库管理,内核并不了解它们。用户线程最终必须映射到相应的内核级线程。轻量级线程(LWP)。
竞争范围:用户线程和内核线程的区别之一是它们是如何被调度的。在执行多对一模型和多对多模型系统上,线程库调度用户级线程到一个有效的LWP上运行,这被称为进程竞争范围(process-contention scope,PCS)方法,因为CPU竞争发生在属于相同进程的线程之间。为了决定调度哪个内核线程到CPU,内核采用系统竞争范围(system-contention scope,SCS)方法来进行,竞争CPU发生在系统所有线程中,采用一对一的模型的系统,调度仅使用SCS方法。
PCS是根据优先级完成的。
Pthread调度:在线程生成过程中允许指定是PCS或SCS的。

算法评估:选择算法的准则。准则可包括如下参数:一是,最大化CPU使用率,同时要求最大响应时间为1s;二是,最大化吞吐量,例如,要求(平均)周转时间与总的执行时间成正比。
确定模型:评估方法(1)分析评估法(analytic evaluation),使用给定算法和系统负荷,产生一个公式或数字,以评估对于该负荷算法的性能。(2)确定模型法(deterministic modeling),采用特殊预先确定的负荷,计算在给定负荷下每个算法的性能。*比较:确定模型不但简单快速,它给出了数字,以允许人们对算法进行比较。然而,它要求输入为精确数字,而且其答案只适用于这些情况。确定模型算法的主要用途在于描述调度算法和提供例子。而且对于一组例子,确定算法可表示趋势以供分析和证明。
排列模型:在许多系统上运行的进程每天都在变化,因此没有静态的进程(或时间)集合用于确定模型。然而,CPU和I/O区间的分布是可以确定的。这些分布可以被测量,然后近似或简单估计。其结果是一个数学公式以表示特定CPU区间的分布。通常,这种分布是指数的,可用其平均值来表示。类似的,进程到达系统的时间分布(即到达时间分布)也必须给定。根据这两种分布,可以绝大多数算法计算平均吞吐量、利用率和等待时间等。
计算机系统可描述为服务器网络。每个服务器都有一个等待进程的队列。CPU是具有就绪队列的服务器,而I/O系统是具有设备队列的服务器。知道了到达率和服务率,可计算使用率、平均队列长度、平均等待时间等。这种研究称为排队网络分析(queuing-network analysis)。
排队分析可用于比较调度算法,但它也有限制,复杂算法或分布的数学分析可能难于处理。到达和处理分不被定义成不现实的但数学上易处理的形式,而且也需要一些不精确的独立假设。这些困难产生的结果是,队列模型只是现实系统的近似,计算的结果也值得怀疑。
模拟(simulation):模拟涉及对计算机系统进行建模。软件数据结构表示系统的主要组成部分。模拟程序有一个变量以表示时钟;当变量值增加时,模拟程序会修改系统状态以反映设备、进程和调度程序的活动。
驱动模拟的数据可有许多方法产生:随机数生成器、数学地或经验地加以定义。
跟踪磁带监视事件发生的顺序。
模拟通常需要数小时的计算时间,昂贵。越精确,所需时间越多,跟踪磁带需要大量的存储空间。模拟程序的设计、编码、调试是其主要的工作。
实现:它是唯一完全精确的方法,是对它进行编程,将它放在操作系统内,并观测它如何工作。这一方法将真实算法放入操作系统,然后在真实操作系统内进程评估。
高昂的代价,所引起的代价不仅包括对算法进行编程、修改操作系统以支持该算法(以及相关的数据结构),而且包括用户对不断改变操作系统的反应。此外,所使用的环境会发生改变。
最为灵活的调度算法可以为系统管理员和用户所改变,以使其能为特定的应用或应用集合所调节。也可以使用API来修改进程或线程的优先级。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值