005❤请谈谈你对进程调度的理解
前言
CPU调度是操作系统的基本功能。每当CPU空闲的时候,操作系统就会从就绪队列中选择一个程序来执行。进程选择由短期调度程序执行。
CPU调度决策一般发生在如下四种情形。
-
当一个进程从运行状态切换到等待状态。
-
当一个进程终止。
-
当一个进程从运行状态切换到就绪状态。
-
当一个进程从等待状态切换到就绪状态。
1,2两种情形下,操作系统必须选择一个新的进程去执行。当调度只出现1,2两种情形的时候,调度方案是非抢占式的。1是进程需要等待某种事件的发生(例如,等待打印机,等待子进程),主动让出CPU。2是进程终止了,它的所有资源都被操作系统回收,CPU处于空闲状态。也是主动让出了CPU。所以这两种情形下的调度其实是等待进程自动让出CPU的。采用非抢占式调度,一个进程一旦拥有了CPU,那么它会一直使用CPU直到它主动让出CPU为止,主动让出就是1,2两种情形。
抢占式调度是进程让出CPU不是主动的,自愿的。上面3,4就是。例如一个中断来了,进程就需要从运行状态切换到就绪状态。执行中断程序。进程等到了某个事件的发生,它将会从等待状态切换为就绪状态,然后它就可以试图去抢占CPU。抢占式调度是有代价的。而且代价比较大。
CPU调度是由内核进行的,这个短期调度程序在进行调度之后,需要切换上下文,切换到用户模式,跳转到用户程序的合适位置来重新启动这个程序。对于现在的交互式系统,人们对系统的响应时间和等待时间的要求是很高的。响应时间长了,用户就会觉得很卡。
一、先到先服务(first-come,first-served)
先到先服务很容易理解。先来的程序先执行,执行完毕后让出CPU给接下来到来的程序。这种策略可以使用FIFO的队列来容易实现。这样的调度策略实现简单,但是它的平均等待时间一般是较长的。更为糟糕的是,当正在执行的程序是一个有许多I/O操作的进程,那么这将导致CPU在空闲的时间里无法运行后面等待的进程,造成了CPU空闲。FCFS策略是非抢占式的,一旦CPU分配给某个进程,那么直到该进程结束之前,CPU都是属于该进程的。从CPU利用率这个指标来评估FCFS,它并不是一个很好的调度策略。
二、最短作业优先调度(shortest-job-first)
最短作业调度是将后续具有最短处理时间的进程先放到CPU上运行,如果就绪队列中有同样长度的进程,那么它们之间是采用FCFS调度的。最短下一个CPU区间,需要操作系统知道接下来是那个进程的CPU区间最短。SJF就是调度这个最短CPU区间的进程。SJF算法具有最短的平均等待时间,它是最佳的调度算法。但是SJF面对的难题是恐怖的,那就是操作系统是如何获知后面就绪队列中哪一个进程具有最短的CPU区间。对于一个批处理系统而言,这不是问题,因为用户会设定进程执行时间。但是现代的操作系统是多任务的交互式系统,操作无法获知下一个CPU区间的长度,我们只能去近似SJF,而不能做到SJF。近似的方法就是去估计,预测它的值。可以认为下一个CPU区间的长度和以前的相似。下一个CPU区间通常可以预测为以前CPU区间的测量长度的指数平均。
SJF算法可以是抢占的,也可以是非抢占的。一般而言,抢占式的SJF算法比非抢占式的SJF算法更好一些,但这需要调度程序优化的非常好,在切换上下文的时候能极快速的做完。抢占式的SJF是指最短剩余时间优先,当正在执行的进程剩余执行时间和就绪队列中进程剩余执行时间相比,其中时间最短将会被优先执行。
三、优先权调度(priority-scheduling algorithm)
SJF算法可以看做是时间优先级的一种优先级调度算法。在现代的操作系统中,每一个进程都会有一个优先权与其相关。具有最高优先级的进程会被分配到CPU。具有相同优先级的进程按照FCFS算法调度。优先权可以通过内部或者外部方式来定义。优先权调度可以是可抢占的或者非抢占的。
优先权调度算法的一个主要问题是无穷阻塞问题(饥饿)。优先权调度会使得低优先级的进程可能在无穷等待CPU的到来。通常这种情形发生的时候,可能就会导致很严重的后果。老化是一种解决该问题的方案,老化以逐渐增加在系统中等待很长时间的进程的优先级。
3.1 时间片轮转法(round-robin)
时间片轮转法是专门为分时系统设计的。它是现代的桌面系统,服务器系统广泛采用的一种调度策略。它定义一个较小的时间单元,称为时间片。CPU调度程序为每个进程分配不超过一个时间片间隔的CPU时间。时间片轮转算法的关键在于时间片大小的选择。
RR算法的性能基本取决于时间片设计的大小是否合理。时间片设计的过大,将会导致响应很慢。这时候的RR算法可能就接近于FCFS算法。同样,如果时间片设计的很小,那么RR算法可以看做是处理器共享的。但是这样会使得每个进程的处理速度都下降到1/n(假设n个进程),上下文切换对于RR算法的影响也是非常大,频发的在进程之间切换可能会导致开销的时间占比很大,相应的进程实际的执行时间就会被压缩。所以时间片的大小选择是RR算法的核心问题。
3.2 多级队列调度(multilevel queue)
将就绪队列分成多个独立的队列。根据进程的某些属性,将进程永久的分配到某个队列之中。每个队列都有自己的调度算法。同时队列与队列之间有调度,通常采用固定优先级可抢占式调度。
也可以在不同的队列之间划分时间片,每个队列拥有一定的CPU时间。
3.3 多级反馈队列调度
对于多级队列调度算法,进程会被永久的分配至某个队列。这样不够灵活。多级反馈队列调度允许进程在队列之间移动。它依据不同CPU区间特点来划分进程。如果进程使用的CPU时间过多,那么它将会被移到更低优先级的队列。目的是将I/O约束和交互式进程留在较高的优先级。以增加系统的响应。当然了,当它在低优先级等待的时间过长了,老化算法就会让它提升优先级。这样,进程的优先级就会是一个动态的变化。
多级反馈队列调度是现在的大多数操作系统普遍采用的方案。