【操作系统】5、CPU调度策略
CPU调度的概念:
见之前写的“CPU管理的直观想法和多进程图像”
CPU调度的动机
面对诸多的场景,如何设计调度算法呢?首先,我们要明白我们的算法应该让什么更好呢?
面对客户:银行调度算法的设计目标应该是用户满意; 而面对进程:CPU调度的目标应该是进程满意。
那怎么才能让进程满意呢?那就是时间了。进程希望尽早地结束任务,这就是周转时间(从任务到达到任务结束)要短,而且希望用户的操作能够尽快地被响应,这就是响应时间(从操作发生到响应)要短。而且系统内耗时间要少,吞吐量(任务的完成量)要大,系统需要把更多的时间用在任务的执行上,而不能老是去做无关紧要的事情,例如:频繁切换任务,切换栈,分配资源等事情。
同时,系统还要去合理地调配任务。那么,CPU的调度策略如何做到合理呢?首先得明白系统中有以下的几种矛盾。
1.吞吐量和响应时间之间有矛盾响应时间小=>切换次数多=>系统内耗大=>吞吐量小由于需要较短的响应时间,那么就得频繁地切换任务,这样系统的很多时间都花在切换任务上面了,系统的内耗大了,吞吐量就小了。
2.前台任务和后台任务的关注点不同前台任务关注响应时间,后台任务关注周转时间。前台任务例如我们的word文档,我们打一个字,需要立马显示在文档中,这就是word文档这个任务关注的是响应时间;而后台任务中,例如我们的javac编译java代码,它的周转时间要小,即该任务从进入到结束所花的时间要小,即编译完成的时间要小。
3.IO约束型任务和CPU约束型任务各有各的特点IO约束型任务就是使用CPU的时间较少,进行IO操作的时间较长,CPU约束型的任务就是使用CPU的时间较长。因此,要做到合理,需要折中、综合考虑以上的几种矛盾。
基本的CPU调度策略:
1、先到先服务(FCFS):
采用这种方案,先请求的进程先得到CPU,由于是非抢先调度,所以一个进程得到CPU后,会一直占用CPU到该进程结束。
- 优点:简单,理解容易
- 缺点:进程平均等待时间长,假设一组进程(P1, P2, P3),所需时间(24, 3, 3), CPU执行长度按ms记,按照FCFS算法,执行顺序为(P1, P2, P3)则平均等待时间为 (0 + 24 + 27) / 3 = 17ms,如果执行顺序为(P2, P3, P1), 则平均等待时间为(0 + 3 + 6) / 3 = 3ms,这个减少是相当大的
这个算法将每个进程与下次CPU执行的长度关联起来,当CPU变为空闲时,它会被赋给CPU执行时间最短的进程。
参考:
对于任意一组给定的进程,SJF算法的平均等待时间最小,因为总是可以通过把短进程移到长进程之前,来使平均等待时间减少。
- 优点:如果能够实现将是最优的。
- 缺点:这个算法有一个附加的问题,就是如何准确地知道每个进程所需要的时间,这是很困难的,所以SJF算法经常用于长期调度,将用户提交作业时指定的进程时限作为长度。
3、优先级调度(priority-scheduling):
每个进程都有一个优先级,进程的执行顺序按照优先级,SJF算法也属于优先级调度,其优先级为CPU执行时间的倒数,优先级调度可以是抢占的或非抢占的。
该算法的一个问题是可能导致无限阻塞或饥饿,一个解决的办法称为老化,每隔一段时间就将所有处于等待状态的进程的优先级提高一级,这样可以证明,在不超过一个常数的时间内,所有进程都会执行。
该算法的一个问题是可能导致无限阻塞或饥饿,一个解决的办法称为老化,每隔一段时间就将所有处于等待状态的进程的优先级提高一级,这样可以证明,在不超过一个常数的时间内,所有进程都会执行。
4、轮转(RR):该算法是专门为分时系统设计的,类将一个较小的时间单元定义为时间片,通常为10ms~100ms,就绪队列为一个循环队列,为每一个进程分配不超过一个时间片的CPU,如进程(P1, P2, P3)对应的CPU为(24, 3, 3),如果使用4ms的时间片,那每个时间片中执行的进程为(P1, P2, P3, P1, P1, P1, P1, P1),等待时间6ms, 4ms, 7ms, 平均等待时间为 (6 + 4 + 7) / 3 = 5.6667ms。
说到这里,SJF是关注系统的平均周转时间,而RR算法是关注系统的响应时间,但是如果一个系统需要响应时间小和周转时间小同时存在,那该怎么办?
比如word很关心响应时间,而javac编译java程序更关心周转时间,两类任务同时存在该怎么办?
即前台的任务更关心响应时间,因为前台任务是与用户直接进行交互的,需要快速响应用户的请求,后台任务更关心周转时间,需要快速的结束任务的。
一个很直观的想法,定义前台任务和后台任务两条队列,前台使用RR算法,后台使用SJF算法,只有前台任务没有时才调度后台任务。
但是这样又会产生问题,如果一直有前台任务怎么办,那这样后台任务就永远得不到调度了。
在这里有一个有趣的小故事:1973年有位工作人员去关闭MIT的IBM7094计算机时,发现有一个进程在1967年提交但一直未运行。
这时候我们可以让后台的任务优先级动态升高,但后台任务(用SJF调度)一旦执行,那前台任务的响应时间又得变大了。
如果我们前后台任务都用时间片,那又退化为了RR算法。
所以,问题还有很多等着我们去发现去想办法解决。
如我们怎么知道哪些是前台任务那些是后台任务呢,前台任务难道就没有后台任务的工作?后台任务难道没有前台任务的工作?SJF中的短作业优先如何体现?如何判断作业的长度?
参考:
1、https://zhuanlan.zhihu.com/p/111813230
2、https://zhuanlan.zhihu.com/p/142812907
3、https://zhuanlan.zhihu.com/p/96837740