调度的基本概念
当有一堆任务需要处理的时候,但是我们的资源有限,无法同时处理这些任务,所以我们就需要一种规则来决定处理这些任务的顺序,这个就是我们的调度
。在现在我们的计算机中,进程的数量都是多于处理机的个数的,这样我们就不能同时并行的处理计算机中的各个进程。
处理机调度: 就是从进程的就绪队列中按照一种规定的算法(高效,公平)来选择一个进程将处理机分配给他运行,用来实现进程的并发执行。
调度的三个层次
高级调度(作业调度)
由于计算机内存是有限的,有时无法用户提交的作业全部放入计算机的内存中,所以这个时候我们就需要一种规则来决定将将作业调入内存的顺序。这个时候可能会有疑问了,作业是什么,老师批改的作业吗,当然不是了,作业是一个比程序更为广泛的概念,它不仅包含了通常的程序和数据,而且还应配有一份作业说明书。系统通过作业说明书控制文件形式的程序和数据,来对他的执行进行控制,并且会在系统中建立JCB(Job Control Block,作业控制块)的数据结构JCB 中包含了系统对作业管理和调度所需的全部信息,其中也包含它的类型,系统就会根据这个类型将它放到相应的后备队列(外存) 中等待作业调度。而且在批处理系统中,作业是从外存调入内存的基本单位。
高低调度(作业调度),是按照一定的原则从外存中处于后备队列的作业中挑选一个或多个作业,给他们分配内存等必备的资源,并且为他们建立相应的进程(建立PCB),让他们有竞争处理机的权力,我们要注意的是,高级调度是内存和外存之间的调度的,每一个作业只调入一次,调出一次。作业调入的时候会建立相应的PCB,调出的时候才会撤销对应的PCB。高级调度一般都是指调入的,因为只有调入的时机才需要操作系统做判断,调出的时候绝对是作业执行完毕结束才调出的。
作业调度主要用于多道批处理系统,在分时和实时系统中不设置作业调度。作业调度的执行频率较低,通常为几分钟一次。
中级调度(内存调度)
由于有虚拟存储技术,可以将暂时不能允许的进程调出到外存进行等待,等他重新重新具备了允许条件的时候,并且内存有空闲时间的时候,在重新调入内存。疑问?虚拟存储技术是什么,一个进程在运行的时候,我们只把用得到的信息读入内存,用不到的信息不读入内存,放在外存中,当我们需要这个数据的时候,再读入内存。这就是虚拟存储技术。对于我们用户来说,我们可以使用的内存好像要比实际内存要大一些,这个就是虚拟内存。
我们为什么要这样做呢,调来调去的不麻烦吗。这样做的目的是为了提高内存的利用率和系统吞吐量(见下文)。暂时调到外存等待的进程状态称为挂起状态,我们需要注意的是,PCB是常驻在内存里的,换出的只是数据段和文本,PCB会记录进程数据在外存中的存放位置,进程的状态等信息,操作系统通过内存中的PCB来对各个进程进行监控,管理。被挂起的进程PCB会被放在挂起队列中,调入的时候会修改PCB状态为就绪状态,挂在就绪队列上等待。
中级调度(内存调度),就是决定将哪个挂起进程重新调入内存中,一个进程可能被多次调入调出内存,因此,中级调度的发生频率要比高级调度发生的频率更高。
低级调度(进程调度)
其主要任务是按照某种方法和策略从就绪队列中选取一个进程,将处理机分配给它。进程调度是操作系统中最基本的一种调度,在一般操作系统中都必须配置进程调度。进程调度的频率很高,一般几十毫秒一次。
三级调度的关系
从图中我们可以看出,首先作业是在后备队列中的,也就是外存中,通过高级调度(作业调度)给对应的作业建立PCB,让他们进入到就绪队列中的,获得竞争处理机的权力。挂起分为阻塞挂起和就绪挂起,分别就是进程处于就绪态或者阻塞态的时候,进程被调出内存,调到外存中的。并且阻塞挂起可能会因为对应的事件发生了变成就绪挂起,所以图中有三个队列,并且阻塞挂起队列有一个箭头指向就绪挂起队列,中级调度(内存调度)从就绪挂起队列中将对应的进程调入内存,并且将状态修改为就绪态。低级调度(进程调度)就是给就绪队列的进程分配时间片。
三层调度的对比
调度的时机,切换过程和方式
什么时候进程进程调度
进程调度就是从就绪队列中选择一个进程为其分配处理机。
- 进程主动放弃处理机
- 进程正常终止
- 运行过程中发生异常终止
- 进程主动请求阻塞(等待 I/O操作)
- 进程被动放弃处理机
- 进程的时间片使用完毕
- 更高优先级的进程进入就绪队列
- 有更紧急的事情需要处理(I/O中断)
什么时候不能进行进程调度
- 在处理中断的过程中:中断处理过程复杂,在实现上很难做到进程切换,而且中断处理是系统工作的一部分,逻辑上不属于某一进程,不应被剥夺处理机资源。
- 进程在操作系统内核程序临界区中:进入临界区后,需要独占式地访问共享数据,理论上必须加锁,以防止其他并行程序进入,在解锁前不应切换到其他进程运行,以加快该共享数据的释放。
- 在原子操作过程中:原子操作不可以中断,需要一气呵成(如之前的的修改PCB的状态,并且放入就绪队列中),原子操作不可以进行进程调度。
进程的调度方式
- 非剥夺调度方式: 又称非抢占式,即 只允许进程自己主动放弃处理机,尽管运行过程中有优先级更高的进程进入就绪队列,也只有等该进程执行完毕或者进入阻塞态才会放弃处理机,这个时候才将处理机分配给优先级高的进程.
优点
是实现简单、系统开销小,适用于大多数的批处理系统,但它不能用于分时系统和大多数的实时系统 。 - 剥夺调度方式: 又称抢占式,一旦运行的过程中有优先级更高进程进入就绪队列,那么该进程就会立刻放弃处理机,将处理机分配给优先级更高的那个进程,可以优先处理更紧急的进程,也可实现让进程按照时间片轮转执行的功能(通过系统时钟).
进程的切换
进程的切换就是从就绪队列中选择一个进程,这个进程可以是刚刚暂停的进程,也可以是其他进程,然后进行处理机的释放和占有,原先的进程释放处理机的时候会将自己进程的各个数据保存,新进程占有处理机的时候会将自己原先PCB中的数据进行恢复,如程序状态字,程序计数器,数据寄存器等.
**注意:**进程的切换室友时间代价的,如果频繁的进行进程的切换,调度,那么必然会使整个系统的效率降低,使系统的时间都花在进程切换上面了,执行进程的时间就变少.
调度算法的评价指标
- CPU利用率: CPU工作时间/总时间
- 系统吞吐量: 表示单位时间内执行的作业数量,长作业执行时间长,系统吞吐量就会降低.短作业执行时间短,系统吞吐量就会提高. 所以不同的调度算法的系统吞吐量会有很大的不同.系统吞吐量=完成作业总数/总共所花时间
- 周转时间: 指作业提交时一直到完成所需的时间,包括等待,排队,调度等时间.
- 作业周转时间: 作业完成时间 - 作业提交时间
- 平均周转时间: 各作业周转时间之和/作业总数
- 带权周转时间 作业周转时间/作业实际运行时间
- 平均带权周转时间 各作业带权周转时间之和/作业数
- 响应时间: 从用户提交到首次产生响应的时间
- 等待时间: 进程/作业等待被服务的时间之和
调度算法
先来先服务(FCFS)算法
- 如果由于作业调度时,每一次都是选择最先进入后备队列的作业,如果是进程调度,每一次选择最先进入就绪队列的进程。
- 他是非抢占式的算法,只能进程自己主动释放处理机。
优点
:公平,算法实现简单缺点
:排在长作业后面的短作业需要等待很长的时间,带权周转时间很长,对于短作业的用户十分不友好,即 对于长作业比较友好,对于短作业不友好。- 由于是非抢占式的,每个进程都会被执行,所以他是不会发生进程饥饿现象的。
短作业优先(SJF)算法
- 追求最小的等待时间,最小的平均周转时间,最小的平均带权周转时间。
- 最短的进程/最短的作业会被先服务(最短指的是服务时间最短)。
- 他既可以用于作业调度,又可以用于进程调度,如果用于进程调度的话,被称为 短进程优先算法(SPF)。
- SJF和SPF都是非抢占式的算法,但是他们也有抢占式的版本–最短剩余时间优先算法(SRTF)
最短剩余时间优先算法
:每当有进程加入就绪队列的时候就需要调度,如果新进程的剩余时间比当前进程的剩余时间要更短,那么当前进程就释放处理机,回到就绪队列,并且让新进程占有处理机。当然,当一个进程执行完毕的时候也会发生调度。优点
:最短的等待时间,平均周转时间,当然,对于SRTF来说,还是SRTF的效果更好。缺点
:不公平,对于短进程有利,对于长进程不利。如果源源不断的有短进程进入就绪队列的话,那么长进程就会一直得不到服务,产生饥饿现象,如果长时间得不到服务,则被成为饿死
。而且,对于进程的服务时间,是由用户来进行提供的,并不一定真是,用户可以自己修改,并不一定是短进程优先。
高响应比优先算法(HRRN)
- 既要考虑进程的等待时间,又要考虑进程要求服务的时间
- 响应比=(等待时间+要求服务时间)/ 要求服务时间
- 非抢占式的调度算法,只有当前进程主动放弃CPU的时候,才会发生调度,从就绪队列中选择响应比最大的那个进程,然后给其分配处理机。
- 等待时间相同时,服务时间短的进程优先执行(SJF的优点)。服务时间相同时,等待时间长的进程先运行(FCFS的优点)。
- 对于长作业来说,如果长时间等待的话,那么等待时间边长,响应比就会变大,从而就避免了长作业饥饿的现象,所以不会发生饥饿现象。
在这里我们需要注意的是,上面的三种算法只是单纯的考虑到了服务时间和等待时间对系统的整体性能的影响,但是不考虑响应时间,不考虑任务的紧急程度,用户交互性比较差,所以只适用于早期的批处理系统。FCFS算法也经常结合着其他的算法一起使用,现在也有比较重要的作用。
时间片轮转算法(RR,Round-Robin)
- 按照各个进程到达就绪队列的顺序,依次的让各个进程执行一个时间片,如果一个时间片内进程没有执行完毕,那么就剥夺处理机,让进程重新进入就绪队列。
- 只可以用于进程调度,因为只有进入内存,建立了PCB后,才可以被分配时间片进行执行。
- 抢占式的,因为当进程在一个时间片内没有执行完毕的时候,就会被强行剥夺处理机让后重新进入就绪队列,由时钟装置发出时钟中断来通知CPU时间片已到。
优点
:公平,响应快,适用于分时系统缺点
:因为高频率的进程切换,有一定的系统开销,不区分任务的紧急程度。- 如果时间片过大的话,那么就是FCFS算法了,太小的话,那么就会进行频繁的进程切换,系统开销太大。一般来说,设置时间片要让系统开销不超过1%。
优先级调度算法
-
在作业调度中,优先级调度算法每次从后备作业队列中选择优先级最高的作业, 将它们调入内存,分配资源,创建PCB井放入就绪队列。在进程调度中,每次从就绪队列中选择优先级最高的进程,将处理机分配给它,使之投入运行。
-
该算法可以分为:抢占式和非抢占式。非抢占式只有进程主动放弃处理机的时候才会发生调度。抢占式,只要有进程加入就绪队列,就绪队列发生变化,并且此时有优先级更高的进程,那么当前进程就释放处理机,优先级更高的那个进程抢占处理机。
-
而根据进程创建后其优先级是否可以改变,可以将进程优先级分为以下两种:
- 静态优先级:优先级是在创建进程时确定的,且在进程的整个运行期间保持不变。
- 动态优先级:在进程创建的时候会有一个初始值,在运行过程中,根据进程情况的变化动态调整优先级。
-
一般情况下: 系统进程优先级高于用户进程,前台进程优先级高于后台进程。操作系统会更偏好I/O型进程(I/O繁忙型进程),因为I/O设备可以和CPU并行执行,让I/O繁忙型进程优先执行的话,那么I/O设备就会更有可能被优先执行。
-
采用动态优先级的话,我们一般要做什么调整呢。如果一个进程在就绪队列等待了很长时间,那么我们就提高他的优先级。如果一个队列占用了处理机运行了很长时间,那么我们就降低他的优先级。对于一个进程频繁的进行I/O操作,我们可以适当的提高他的优先级。
多级反馈队列调度算法
FCFS的算法是公平,SJF是短作业优先,有着较好的平均等待时间和周转时间,RR算法可以让每个进程都可以很好的响应,优先级调度算法可以灵活的调整各个进程被服务的机会。而多级反馈队列调度算法,就是对上面算法的优点和缺点进行一个折中的一个算法。
算法规则:
- 设置多个就绪队列,各级队列优先级从小到大,时间片从小到大。
- 新进程到达的时候优先进入第一级队列,按照FCFS的原则依次等待分配时间片,如果时间片用完进程还没有运行结束,那么该进程就会进入下一级就绪队列队尾,同样按照FCFS的原则等待时间片的分配,如果已经是最后一级队列,那么就会加入该队列队尾。
- 只有第K级队列为空的时候,才会为第K+1级队列分配时间片。
- 如果一个进程正在执行的时候,有一个新的进程进入了一级队列,那么该进程就会立刻释放处理机,进入当前就绪队列队尾,新进程抢占处理机。
算法优点:
- 各个进程相对公平(FCFS的优点)。
- 短作业往往只需要较短的时间就会被执行完毕(SJF的优点),并且不用记录进程的执行时间(避免用户作假)
- 每个新进入的进程都会很快的得到响应(RR的优点)
- 可以灵活的调整对进程的偏好程度,比如I/O进程让他一直加入当前队列的队尾,不进入下一级队列,这样他就可以一直保持较高的优先级。
- 会发生饥饿现象,如果一直源源不断的有新进程进入的话,那么处于优先级较低队列的进程就会长时间得不到服务,可能被饿死。
因为现在的交互式操作系统更偏重于响应时间,公平性和平衡性等指标,而RR,优先级算法和多级队列调度算法能更好的满足这些要求,所以这三种算法适用于交互式操作系统。
小结
调度层次:
- 高级调度(作业调度):从后备队列中选择一个作业创建对应进程并放入就绪队列,发生频率最低。
- 中级调度(内存调度):将内存中暂时不使用的进程调出内存,PCB仍在内存中,发生频率中等。
- 低级调度(进程调度):从就绪队列中选择一个进程为其分配处理机,发生频率最高。
进程的调度方式
- 非剥夺式: 当前进程主动释放处理机时,才会发生调度。
- 剥夺式: 当有更紧急的任务进入就绪队列时,就会发生调度。
调度算法
- FCFS:选择最先进入就绪队列的。
- SJF: 选择服务时间最短的,作用于进程调度,成为SPF。
- HRRN:从就绪队列中选择响应比最高的,分为抢占式和非抢占式。
- RR:为就绪队列的进程依次分配一个时间片,时间片完进程没有执行完毕,加入队列队尾。
- 优先级调度算法:抢占式和非抢占式,选择优先级最高的。
- 多级反馈队列调度算法:多个优先级不同的队列,各个队列时间片不同,进入时先加入一级队列,分配时间片,时间片结束没有运行完毕,加入下一次队列。