谈谈进程调度那些算法
![](https://img2022.cnblogs.com/blog/1264490/202207/1264490-20220727131808726-32169412.png)
本文假定在单核CPU的情况下进行描述
进程调度定义
在操作系统发展史以及前一期进程基础知识讲到了多进程并发的概念,虽然从表面上看,有多个进程在同时执行,但是在单核CPU下,任何时刻都只可能有一个程序在执行,比如正在计算1*2这个程序A,那么就不能运行1+...+n这个求和程序B,这个时候程序A处于执行状态,而程序B处于非执行状态。那么就有一个需要解决的问题:我们在任意时刻到底是执行哪个程序呢?
我们运行的地铁列车,有指挥中心统一控制调度,到底由哪些地铁执行哪一天的任务,这是因为轨道等资源有限,不可能全放进去。类似到进程调度,CPU等硬件资源有限,也不可能全部一起执行。这就引出了我们的进程调度。
一般来说程序在CPU上执行有3种模式:
-
计算密集型,这类程序需要更多的CPU资源,占用更多的CPU时间来运行程序,比如计算解高阶方程、矩阵乘法等需要大量计算的程序上。
-
IO密集型,这类程序需要频繁进行IO操作,而在进行IO操作时CPU就闲置下来了,显然这类程序只需要在IO准备好的情况拿到CPU的执行权限就能非常高效。比如播放PPT这类程序。
-
平衡型,这类就是在IO和计算两个方面均衡,比如下载文件等等,这类程序在响应和周转之间得到平衡就显得重要。
了解完上面的三种程序,操作系统的最大目标是让三类程序都尽可能的高效执行。
调度的目标
CPU调度的目标就是尽可能的减小每个程序的响应时间,即减小系统的平均响应时间,尽可能的提高系统的吞吐率,保持系统各个部件都处于繁忙状态,就得提供某类公平的调度机制来达到这一目的。
抢占与非抢占式
抢占式的意思就是,当CPU在运行程序A时,CPU的执行权限能够通过操作系统被程序B抢占,从而让程序A进入等待执行状态。
对应的非抢占式就是在程序A执行时,它会一直执行下去,一直到它执行完毕或者进入阻塞状态才交出CPU执行权限,让其他程序执行。
调度算法
下面来看看4种常见的也是面试中问得最多的算法。
先来先服务算法
先来先服务调度算法缩写为FCFS(First Come First Serve)。哪个任务先来就先执行哪个任务。这个比较容易想到,先到先得,非常公平,后面来的任务,老老实实排队就完了,我们在银行办理业务的时候也是这种排队情形。
这类调度算法不能别抢占,比如新来的一个程序,需要抢占正在执行的CPU,但是在这种算法的调度下,是不能够发生的,那么这样就会带来一个问题:某个任务正在等待IO,且需要的时间很长,这个时候不能被抢占的话,其他程序也没机会执行,这就影响了整体效率,这其中如果一个短时间任务程序需要等待这个IO操作完成后执行的话,很明显执行完这个任务的时间将会大大变长。
下面看个例子
现在有两个程序:A需要运行10秒,B需要运行1秒。A程序与B程序几乎同时启动,但B比A慢了一点,排在A之后执行,则需要等待10秒。这样A的响应时间为10秒,而B的响应时间则为11秒,从而平均响应时间10.5秒。那么响应时间对于B来说很慢。
时间片轮转算法
时间片轮转算法是对先来先服务算法的一种改进,其主要目的是改善短程序的响应时间。这种调度算法采用的办法就是周期性的进行执行任务的切换。比如每1秒钟切换一次执行程序,如下图。
再来看看FCFS算法中提到的例子。
A 需要运行10秒,B需要运行1秒。使用FCFS时系统平均响应时间为10.5秒。而使用时间片轮转,则A在执行1秒后,CPU切换到进程B,在执行1秒后,B结束,A接着执行9秒。这样A的响应时间是11秒,而B的响应 时间为2秒。系统的平均响应时间是6.5秒。这显然比FCFS的效率强多了,效率将近提升40%。
上面例子中,我们其实还可以发现,如果要想减少B的响应时间,可以无限制缩短时间片的间隔时间,理论上,B的响应时间可以无限接近1秒。但是反过来思考,如果时间片的轮子时间间隔增大到10S呢,那对于B来说,响应时间劣化到11秒。所以时间片轮转的时间间隔取多大的值成为了问题,这个问题可以根据系统切换进程的开销以及当前正在就绪队列的进程数可以来做判断。
但是这种算法太过于公平了,每个进程得到的执行时间都是一样的,这样就导致每个进程都不会去优化自身的执行时间,而且时间片的轮转过程中进程切换的开销也是不可忽视的。所以那还有没有更加智能的办法呢?比如有些任务就只需要0.5S,他可以快速执行完,有些任务执行60S,期间插入一个0.5S的任务,对于60S的任务时间感知也不会强烈,所以就出现了短任务优先算法
短任务优先算法
如图,是一种抢占式的短任务优先调度算法,可以看到A的执行时间最短,被最先执行,其次是D任务进行执行,如果是N这类长时间任务,就很难得到CPU的执行权限。
短任务优先算法有两个变种:一种是非抢占,一种是抢占。非抢占短任务优先算法的原理是让已经在CPU上 运行的程序执行到结束或阻塞,然后在所有候选的程序中选择需要执行时间最短的进程来执行。
抢占式短任务优先算法则是每增加一个新的进程就需要对所有进程(包括正在CPU上运行的进程)进行检查,谁的时间短,就运行谁,这种调度算法的一个好处就是大大提高了短任务的响应时间。
但是对于长任务一直得不到运行,就会导致进程“饥饿”,还有一个大的缺点是:系统无法准确知道每个进程到底还要执行多久。
优先级调度算法
上图可以看到,虽然A的执行时间最短,但是不是第一个执行的。因为有优先级的约束,优先级为200的N 最先被执行了。其次是100的程序B在跟着执行。
短任务优先算法有一个缺点是可能造成长时间进程“饥饿”。但这个问题比较容易解决,使用优先级就可以解决。优先级调度算法的原理是给每个进程赋予一个优先级,每次需要进程切换时,找一个优先级最高的进程进行调度。这样,如果赋予长进程一个高优先级,则该进程就不会再“饥饿”。事实上,短任务优先算法本身就是一种优先级调度,只不过它给予短进程高优先级而已。
优先级调度的优点是可以赋予重要的进程以高优先级以确保重要任务能够得到CPU时间。其缺点则与短任务优先算法一样,低优先级的进程可能会“饥饿”。不过,这个问题在优先级调度算法里比在短任务优先里好解决:只要动态地调节优先级就可以了。
调度过程
讲了调度的定义、目标等概念,那么调度到底是如何进行的呢,我们来看看进程的调度过程大致概览:
-
中断请求导致正在运行的进程挂起
-
操作系统获取CPU控制权限
-
操作系统按照相应的调度算法选择下一个执行的进程
-
保护当前进程并准备选中进程的执行环境
-
跳转到新进程执行
到这里全文就结束了,本文主要讲解了进程调度中4种场景的调度算法,以及调度相关的知识,属于操作系统基础性知识。