前言
在进程与线程中,我们介绍过进程的五种状态,还介绍了线程调度状态和调度算法与进程是一样的,本文我们就介绍一下常见的进程调度算法,当然按照我们之前的介绍,这些算法对线程同样适用。
先来先服务(First Come First Serve)
先来先服务的调度方式就和这个算法的名字一样,使用一个队列存储就绪态进程的task_struct,cpu空闲时,就从队列中取出第一个task_struct进行调度,在这个进程处理运行态时,别的进程不可抢占cpu,只能在就绪队列中等待被调度。
先来先服务算法优点是很好理解,实现起来非常简单,对于计算密集型任务,可以一直占用cpu运行,加快计算所需的时间;但存在的问题是如果当前占用cpu的进程需要占用很长时间,会导致就绪队列中的进程等待很长时间无法执行,这在现代多任务的操作系统中是无法忍受的。
短时优先(Shortest Job First)
为了解决先来先服务算法的长进程占用时间长的问题,可以使用短时优先算法,短时优先算法的思路是耗时较短的进程可以优先运行,耗时长的进程需等待短时进程执行完后再执行,短时优先算法为不可抢占时,只能等待进程主动让出cpu,短时优先算法为抢占式时,若进程的执行时间比占用cpu的剩余时间还要小时,将抢占cpu。
短时优先算法的主要问题是如何确定进程的执行时间,通常进程的执行时间是不可预测的,一种解决的方法是近似预测方法,这种方法使用上次cpu的执行时间预测下次的执行时间,预测公式如下:
短时优先算法虽然解决了先来先服务算法的问题,但由于执行时间长的进程可能一直等待而造成饥饿,这对长进程十分不利。
最高响应比(High Response Radio Next)
最高响应比算法是对FCFS和SJF算法的中和,这种算法基于下面的思路对进程进行调度:
- 如果进程等待的时间相同,则执行时间短的进程优先调度;
- 当进程的执行时间相同时,则等待时间长的进程优先调度;
- 进程调度的优先级随着等待时间的增加而提高,避免进程饥饿。
最高响应比算法综合考虑了各种因素,通过上面的规则计算响应比,基于响应比的值进行调度,但缺点是需要付出计算响应比的消耗。
轮转调度算法(Round-Robin)
轮转调度算法为每个进程事先分配一个时间片,当进程占用cpu时,消耗时间片,时间片消耗完毕时,进程必须让出cpu,重新加入就绪队列,当然进程也可以主动让出cpu(如进程阻塞时)。轮转调度算法可以提高平均响应时间,但缺点是如果发生了产生需要紧急执行的进程,RR算法不能立刻执行。
轮转调度算法的主要问题是如何确定时间片的大小,这通常取决于系统的计算能力、对响应时间的要求和就绪队列中进程的数量,时间片应该比大部分进程的执行时间长,这样可以避免频繁的进程上下文切换带来的无谓消耗,但时间片也不能过长,否则就退化为了FCFS算法,具有FCFS算法的缺点,通常的标准是时间片应该长于80%的进程的执行时间。
完全公平算法(Complete Fair Scheduler)
CFS算法为每个进程分配一个虚拟运行时间vruntime,所有进程的task_struct被放在就绪队列中,就绪队列实际上是一棵红黑树,红黑树以vruntime为键进行排序,最左侧的节点vruntime最小,CFS算法每次选择最左侧节点中的进程进行调度,进程占用cpu时,vruntime不断增大,不占用cpu的进程vruntime不变,进程让出cpu后,如果还需要被调度,则根据新的vruntime再插入红黑树中等待。
为了解决优先级高的进程应该被优先调度的问题,不同进程vruntime的增加速率是不同的:
进程的权重越大,实际运行时间相同,vruntime会更小,因此也会获得更多的调度机会。进程权重可以通过调整进程的nice值来调整,nice值越大,进程权重越小,获得的调度机会越少,因此对cpu来说更“nice"。