进程调度算法总结
FCFS(First come first serve)先来先服务算法:
简单的排队算法,维护一个队列,后来的只能排在队尾等待。
非抢占。
缺点:不够智能,对于cpu密集型进程不友好,比如:一个只需要1ms运行时间的cpu密集型进程,但是之前有一个要读5s的io密集型进程。那么即使那个cpu密集型进程只需要运行1ms,但是必须等待足足5s才能运行!
SJF(Shortest job first)最短作业优先:
这种算法假设我们可以预测每个进程需要运行的时间。比如有5个进程,分别运行时间是:1,3,2,5,1。
这个算法顾名思义,先取需要最短运行时间的进程来运行,所以执行顺序就是:1,1,2,3,5。其实就是算法里的贪心法。
SJF调度是最优调度(贪心法),但问题是怎么预测运行时间呢?所以其实这个算法只能作为比较,无法真正实现。
非抢占。
SJF算法还有一个变种:最短剩余时间优先。是选择剩余运行时间最少的进程来调度,所以这个算法是抢占的。
RR(Round robin)轮转调度:
每个进程被分配一个时间片,一般为20~50ms。每个进程只能最多使用一个时间片的时间,如果没用完时间片就运行完毕,那么可以直接调度下一个进程;如果用完了时间片还没运行完毕,系统会把该进程重新放到队尾。
时间片的选择是有要求的,因为在切换进程的时候要进行上下文切换。如果上下文切换的时间不比一个时间片小多少,那轮转调度的效率就会很差,因为我们花了太多时间在切换进程上。
由于系统会在一个时间片完成后主动切换下一个进程,所以RR调度算法是抢占的。
优先级调度:
考虑前面说过的RR调度,它对所有进程“一视同仁”。但实际中可不是这样,人有三六九等,进程也分重要不重要。比如前台交互的进程就很重要,需要快点返回结果。如果是后台维护数据的进程,那等一会无所谓。
所以我们对每个进程加上一个优先级(一般是整数),对于高优先级的进程我们优先调度,优先级进程执行完后,再调度低优先级进程。像io密集型进程显然我们应该设置较高的优先级,毕竟这类进程只需要占用一点点的cpu时间,之后工作就交给io硬件了。所以我们应当优先调度io密集型进程,这样经过一点点运行时间,该io密集型进程就不再需要cpu了。所以cpu密集型进程的优先级应该比io密集型进程低。
但这样有一个问题:如果我们不停地加入高优先级的进程(比如为2),但是之前我们有一个优先级为1的进程因为一直被高优先级进程抢占所以从来没有运行过,这肯定不行阿。所以优先级不应该是固定的,比如我们可以将等待时间加入决定因素,随着等待时间变长的,我们逐渐提高它的优先级,这样随着时间推迟,最终该进程会被执行。
将等待时间加入调度因素的优先级调度算法其实就是高响应比优先调度算法:根据“响应比=(进程执行时间+进程等待时间)/ 进程执行时间”这个公式得到的响应比来进行调度。高响应比优先算法在等待时间相同的情况下,作业执行的时间越短,响应比越高,满足段任务优先,同时响应比会随着等待时间增加而变大,优先级会提高,能够避免饥饿现象。优点是兼顾长短作业,缺点是计算响应比开销大,适用于批处理系统。
抢占的。
多级队列调度:
该算法内部会实现多个调度队列,队列1每个进程可以运行1个时间片,队列2每个进程可以运行2个,队列3每个进程可以运行4个,队列4每个进程可以运行8个,以此类推。
假设有n个队列,那么前n-1个队列都是FCFS调度,最后一个队列是RR调度。
对于一个需要执行100个时间片的进程,先加入队列1,运行1个时间片后放入队列2。再运行2个时间片后放入队列3。最终这个进程我们需要1+2+4+8+16+32+64,一共7次上下文切换。如果我们使用上面说的RR算法,需要整整100次!
对于不同队列来说,高优先级的队列如果有进程,那么优先清空高优先级的队列,之后再情况次高优先级的队列,以此类推。。
这种调度算法可以良好的兼顾长进程和短进程。
执行步骤:
抢占的。