CPU调度:对于单核cpu,每个时刻最大可以处理一个进程。cpu作为计算机最重要的资源之一,cpu调度即采用多道程序,多个进程同时位于内存在,当某个进程需要等待时,此时cpu空闲,从内存中找到另外一个进程接管cpu。从而最大化cpu利用率。当一个进程需要等待时,另一个进程接管cpu。
CPU/IO执行周期:对于每个进程,都是周期性的执行cpu执行或是io等待。而cpu调度的成功取决于进程的CPU/IO执行周期。进程不断地在这两个状态之间交替。
CPU调度程序:当cpu空闲时,cpu调度程序从内存中选择一个进程,并为其分配CPU。进程选择采用短期调度程序或是cpu调度程序。就绪队列不是必须为FIFO的,可以是FIFO,优先队列,树等。就绪队列中的所有进程都需要排队以等待cpu空闲,队列内的记录通常为PCB。
需要cpu调度的四种情况:
1.一个进程从运行状态->等待状态(执行IO请求或wait())
2.一个进程从运行状态->就绪状态(中断发生时,cpu将当前进程挂起,当前进程由运行状态转为就绪状态)
3.一个进程从等待状态->就绪状态(如IO请求完成)
4.一个进程终止
非抢占调度:对于第一种和第四种情况,必须选择一个新进程来执行,此时调度方案称为非抢占的(或协作的),即调度方案只有在第1和第4种情况出现时,才进行调度。在这种情况下,一旦某个进程被分配cpu,那么会一直执行,直到该进程终止或它切换到等待状态。
抢占调度:不只在第1和第4种情况下,也进行调度。称为抢占调度。比如某个某个进程并未切换到等待状态,或是终止,也被其他进程挂起,那么称之为抢占。
cpu调度由调度程序来完成,其主要功能包括:1.切换上下文 2.切换到用户模式 3.跳转到用户程序的合适位置,以便重新启动程序。
调度延时:调度程序停止一个进程,并启动另一个进程所需要的时间称为调度延时。
无论是何种cpu调度算法,都要以一些指标来进行,共同的指标或目标有:
cpu使用率:应尽可能让cpu忙碌
吞吐量:单位时间内进程完成的数量
周转时间:从进程提交到进程完成的时间。所有时间段之和,包括等待进入内存,在就绪队列中等待,在cpu上执行和io执行。
等待时间:进程在就绪队列中等待的时间。cpu调度并不影响进程运行和io时间,只影响等待时间。
响应时间:对于交互系统,周转时间不是最佳准则。从提交请求到产生第一响应的时间,称为响应时间,是开始响应所需的时间,而非输出响应所需的时间。而周转时间通常受限于设备速度,如io执行等。
FCFS:最简单的cpu调度算法即为先来先服务算法(First-Come,First-Served,FCFS)。先请求cpu的进程被分配cpu执行,可以通过队列来实现。当进程进入就绪状态时,它的PCB块被放到队列尾,当CPU空闲时,队列头的进程被分配cpu,同时其PCB块被cognac队列首移除。
缺点:平均等待时间往往很长。如果完成时间较长的任务先到达,那么其后的所有任务所需的等待时间都将很长。FCFS是非抢占的, 所以对于分时系统(每个用户都需要获得一定的cpu时间)是特别麻烦的。
SJF:Shortest-Job-First调度算法。将每个进程与下次cpu执行时间长度并联起来,所以更应称之为最短下次cpu执行算法,当cpu空闲时,它会被分配给执行时间最短的进程。
优点:SJF算法是最优的,因此对于给定的一组进程,平均等待时间最小。
缺点:进程在cpu上的执行长度难以确定。因此SJF调度算法常用于长期调度。
根据下个进程的cpu执行时间和当前进程剩余的cpu执行时间,可以形成抢占SJF和非抢占SJF。
抢占SJF:如果下个进程的cpu执行时间小于当前进程剩余cpu执行时间,那么先执行下个进程。
非抢占SJF:即便下个进程的cpu执行时间小于当前进程剩余cpu执行时间,也先执行完当前进程,再执行下个进程。
优先级调度算法:SJF算法是优先级调度的一个特例,根据进程的cpu执行时间来确定优先级。优先级调度将每个进程都与一个优先级关联,具有最高优先级的进程首先被分配cpu执行,具有相同优先级的进程可以根据FCFS。
根据cpu正在执行的进程优先级和就绪队列中进程的优先级,优先级调度也可分为抢占的和非抢占的。
抢占优先级调度:若进程中正在执行的进程优先级低于就绪队列中某个进程的优先级,先执行就绪队列中具有更高优先级的进程,为抢占优先级调度。否则为非抢占优先级调度。
缺点和问题:
无穷阻塞(饥饿)问题:处于就绪队列中的等待cpu空闲的进程被认为是阻塞的,而优先级调度可能让某个低优先级进程无限等待cpu,即一直处于阻塞状态。
解决方法:老化。每隔一段时间,将就绪队列中阻塞的进程优先级提高,这样,原先被无限阻塞的进程,最终一定会具有最高的优先级而被执行。
轮转调度:Round-Robin,RR。是专门为分时系统设计的。类似于FCFS调度算法,但是增加了抢占以切换进程。将一个较小的时间单元定义为时间量或时间片,就绪队列为循环队列,轮转调度程序循环整个就绪队列,为每个进程分配不超过时间片的cpu时间。
执行机制:因为每个进程都被分配了不超过时间片的cpu时间,因而存在两种可能。1.进程执行时间小于时间片。此时进程所占用的资源被释放,调度程序将绪队列头的进程分配一个时间片的cpu时间。2.进程执行时间超过时间片。此时,当时间到达时间片时,定时器产生中断,进行上下文切换,为就绪队列头的进程分配cpu时间进行执行,同时将当前未完成的进程加入到就绪队列的尾部。
缺点:平均等待时间较长。RR算法的性能很大程度上取决于时间片的选取。如果时间片选的太大,那么RR算法和FCFS算法一样。如果时间片选取的过小,那么系统时间将会浪费是频繁的切换上下文上。因此希望时间片远大于上下文切换时间。
抢占:因为时间片的限制,没有任何一个进程可以连续执行超过一个时间片的cpu时间。如果某个进程执行到时间片时间还未执行完毕,那么它会被就绪队列头的进程所抢占。
进程分组:在进程容易被分为不同组的情况下,需要能对不同组的进程分别调度。通常进程分为后台进程(批处理进程)和前台进程(交互进程),这两种进程具有不同的响应时间要求,也有不同的调度需求。另外,前台进程涉及到交互,因而需要有更高的优先级。
多级队列调度算法:将就绪队列分为多个单独队列。每个进程根据内存大小,优先级,进程类型永久分配到一个队列中。每个队列采用不同的调度算法。另外,队列间也需要有调度算法,通常采用固定优先级抢占调度。如前台队列可以比后台队列具有绝对的优先。
多级反馈队列调度:对于多级队列调度,每个进程属于的队列被永久固定。而多级反馈队列调度运行进程在不同队列间迁移。如当进程使用过多的cpu时间,会被移到优先级更低的队列,io密集型进程和交互进程被移到高优先级队列,另外,老化算法将长时间处于等待的进程移到高优先级队列,防止饥饿的发生。
线程:线程分为用户线程和内核线程,内核线程才是系统能调度的。用户线程需要映射到内核线程上,才能被运行到cpu上,而用户线程由线程库管理,对于内核线程不可见。而映射的方法可能不是直接的,而是由LWP(轻量级进程)来实现。
竞争范围:分为进程竞争范围(Process Contention Scope,PCS)和系统竞争范围(System-Contention Scope)。
进程竞争范围:对于多对一和多对多线程映射模型,采用的是进程竞争范围,因为调度的线程,竞争cpu使用的线程属于同一个进程。
系统竞争范围:对于一对一模式,对于决定哪个内核级线程运行在cpu上,采用系统竞争范围,发生在系统的所有线程之间,而不一定是属于一个进程。
非对称处理:一个处理器(主处理器)负责所有调度决定,IO处理和其他系统活动,其他处理器只负责执行用户代码。
对称多处理(Symmetric MultiProcessing,SMP):每个处理器自我调度,所有进程可能处于一个共同的就绪队列里,或者每个处理器都有私有就绪队列。每个处理器的调度程序都检查共同就绪队列,以便选择执行一个进程。
处理器亲和性:大多数SMP系统避免将一个进程从一个处理器迁移到另一个处理器上,而是试图让一个进程运行在同一个处理器上。称为处理器亲和性,即一个进程对执行它的处理器具有亲和性。
内存停顿:当一个处理器访问内存时,花费大量时间等待所需的数据。称为内存停顿。可能由高速缓存未命中而引起。而采用多线程之后,如果一个线程发生内存停顿,那么该核会切换到另一个线程。
软实时系统:不保证调度关键实时进程,而只保证这类进程优于非关键进程。
硬实时系统:一个任务应当在截止之前完成,否则被认为是没有完成
事件延迟:事件发生到事件得到服务的时间,称为事件延迟。
中断延迟:cpu接收到中断到中断处理程序开始执行的时间。如确定中断类型,保存上下文,切换上下文所花费的时间。
调度延迟:调度程序从停止一个进程到启动另一个进程所需的时间。
实时系统的一个重要功能是,当一个实时进程需要cpu时,立即响应。因此实时调度应是支持抢占的优先级算法。根据每个进程的重要性分配优先级。支持抢占的优先级调度仅能够保证软实时,而要保证硬实时,还需要给进程附加调度特征。
单调速率调度:单调速率调度采用可抢占的静态优先级调度策略,来调度周期性任务。
优先级的确定:优先级与每个进程的周期成反比。周期指每个进程下次执行与上次执行的间隔,即优先级与进程执行的频率成正比,执行频率越高的进程优先执行。单调速率调度基于这样的假设:每个进程在cpu上执行的时间相同,此时执行频率越高的进程应保证优先执行。
优点:单调速率调度是静态优先级调度中最优的,如果一组进程不能通过单调速率调度,那么它不能用任何一种静态优先级调度算法来调度。
缺点:CPU利用率总是有限的,不能完全最大化CPU利用率。
最早截止期限优先调度(Earliest Deadline First,DEF):根据截止期限动态分配优先级。截止期限早,优先级越高,截止期限越晚,优先级越低。当一个进程运行时,它应向系统公布截止期限要求。与单调速率调度不同之处在于,单调速率调度的优先级是固定的,因为周期性任务的频率是固定的,而最早截止期限优先调度是动态分配优先级的。
EDF不要求进程是周期性的,也不要求进程的cpu执行长度相同,唯一要求是,进程变成可执行时,公布它的截止期限。
比例分享调度:在所有进程之间分配T股,所有进程的总的为N股。那么确保一个进程有T/N的cpu运行时间。比例分享调度采用准入控制策略,当系统现有股数小于进程的股数时,系统应拒绝该进程运行。
完全公平调度程序(Completely Fair Scheduler,CFS)称为默认的Linux调度算法。
Linux调度基于调度类。每个类都有一个特定优先级。内核根据不同的类,采用不同的调度算法。Linux内核实现两个调度类,使用CFS算法的默认调度类和实时调度类。
CFS调度程序不按照严格标准为每个优先级分配相同的时间片,而是为每个任务分配一定比例的CPU运行时间。每个任务分配的比例按照友好值来计算。CFS没有采用游离的时间片,而是采用目标延迟,即每个可运行任务运行一次所需要的时间间隔。根据目标延迟,按比例分配CPU时间。CFS调度没有直接分配优先级,而是通过维护每个任务的虚拟运行时间变量,来记录每个任务运行多久。
CFS调度的底层采用红黑树实现,值基于虚拟运行时间。当任务就绪时,被放到树中,当任务不可运行时(如阻塞等待IO),被从树上移除。