5.1 CPU调度基本概念
5.1.1 抢占调度 && 非抢占调度
当CPU空闲的时候,操作系统就要从就绪队列中选择一个进程去执行,其实就是选择PCB,这个是由短期调度程序来调度完成的。
CPU的调度可能发生在下面4中情况
- 当一个进程有运行状态切换到等待状态(比如IO请求);
- 当一个进程有运行状态切换到就绪状态(比如终端);
- 当一个进程有等待状态切换到就绪状态(比如IO完成);
- 当一个进程终止。
对于第1和第4种情况,必须选择调度,这个叫做非抢占调度,对于第2和第3则可以做选择,这个叫做抢占调度。 采用非抢占调度是指一旦CPU分配给一个进程,那么该进程会一直使用CPU知道进程终止或者切换到等待状态,这个就是非抢占,否者就是抢占。
5.2 调度准则
为了评价一个调度规则的优劣,有如下几个方面需要考虑:
- CPU使用率:就是需要CPU尽量的繁忙
- 吞吐量:CPU在规定时间的任务处理量
- 周转时间:一个进程从提交到完成的时间总和
- 等待时间:一个进程在就绪队列的时间总和
- 响应时间:一个进程从提交请求到产生第一相应的时间
我们评估一个调度算法就是从上述几个方面考虑的。
5.3 调度算法
CPU的调度处理是指从就绪队列中选择进程并分配CPU去执行,有很多不同的调度算法,如下:
5.3.1 先到先服务First Come First Serve FCFS算法
就是按照到来的时间一次分配CPU,这个情况下平均等待时间往往不是最优的,FCFS属于非抢占的调度算法。肯可能出现所有其他的较短的进程都在等待一个周期较长的进程执行结束,这个叫做护航效果。
5.3.2 最短作业优先调度 Shortest Job First SJF算法
就是选择按照周期由短到长的顺序去分配进程执行,这个可以被证明平均等待时间是最短的,不过这个问题的难点在于如何评估计算下一个进程的周期长度。
因为无法准确预测下一个CPU区间长度,所以SJF算法经常用于长期调度,为了可以在短期调度中使用,特别提出了一个近似SJF算法,采用一个数学函数来模拟预测CPU区间长度。
SJF可以是抢占调度也可以非抢占调度,对于非抢占很简单,这里就不说了。对于抢占调度,其实就是最短剩余时间优先调度Shorest Remaining Time First Scheduling ,就是每当来一个进程评估当前最短的剩余的CPU区间,选择最短的进程抢占CPU。
5.3.3 优先级调度 Priority Scheduling Algorithm
上面的SJF算法其实是优先级调度算法的一个特例,优先级调度同样可以是抢占调度或者非抢占调度。这个村子无穷阻塞现象,也即可以运行但是必须要等待CPU来去执行,就是阻塞现象。低优先级进程的无线等待问题的解决手段就是老化,也即动态的提高等待线程的优先级。
5.4.3 轮转法调度 Round Robin RR
轮转法是专门针对分时系统设计的,它类似FCFS调度,但是增加了抢占以切换进程。
为了试下RR调度,将就绪队列保存在一个FIFO队列,新来的进程添加到队列尾部,CPU调度从就绪队列中选择第一个进程,设置一个时间片,时间一到就立刻发出中断,切换下一个进程,假如该进程在时间片内提前执行结束,那么也立刻中断,未执行完的进程添加到队列尾部。
通过上述描述可以看出,RR调度算法很大程度依赖时间片长度的设计,假如无限大,那么就是FCFS调度了,如果很小,那么就是处理器共享,注意还应该考虑到进程上下文切换的代价。
5.3.5 多级队列调度 Multilevel Queue Schduling
这个是考虑到不同的进程的分组提出的调度算法,多级队列调度算法就是将就绪队列分成多个独立队列,根据进程的属性:比如内存大小、进程优先级、进程类型等等分配到不同的队列,每一个队列可以有自己的调度算法,比如RR、FCFS、SJF等等调度算法,另外队列之间必须要有调度,一般是固定优先级抢占调度。
5.3.6 多级反馈队列调度 Multilevel Feedback Queue Schduling
这个考虑的是进程会永久的分配到一个队列,这个缺点是不够灵活。
为了实现多级反馈队列调度,做法是这样的,先根据不同进程的属性分配到不同的队列中,如果进程使用太多的CPU时间,那么该进程就被移动到低优先级队列中,然后假如一个进程的等待时间过长的进程会被移动到优先级较高的队列中,这个就是反馈。
另外,Linux调度程序是抢占的、基于优先级的调度算法。