为什么要调度
现在都是做事情做任务的个数要远远多于计算机中处理机的个数,处理机就要合理分配资源给目标,这样才能做到办事效率最大化。
否则就是等一个进程执行完,下一个进程才能执行。而在执行的过程中,会需要一些外设输入或等待其他资源,这个过程是很花费时间的,把这些时间利用起来,去执行其他的进程,这样处理机的利用率就会大大增加。
从层次上来看:
- 对作业的调度(高级调度):对后备状态的作业分配资源。发生频率底
- 对内存的调度(中级调度):将不运行或不能运行的进程调出内存。发生频率中等。
- 对进程的调度(低级调度):对就绪队列中的进程分配处理机资源。发生频率高。
不能进行调度的情况:
(先标记上请求调度的标志,以下情况完成后了回来再进行调度。)
-
在处理中断的过程中。
中断处理的过程很复杂,在实现上很难做到进程的调度或切换。
-
进程在操作系统的内核程序里的临界区中。
进入到临界区前,理论上要加锁的,在解锁前,处理机不应该切换到其他进程运行。
-
在原子操作过程中。
在原子操作过程中,连中断都要屏蔽,更不要说进程的调用或切换了。
比较典型的几个调度算法:
-
先来先服务: 选择最先进入队列的
选择最先进入队列的,直到完成了,或阻塞才释放处理机; 属于不可抢占式的。
对执行时间长的作业或进程有利,对短的不利。短的可能会产生饥饿现象。
一般是 优先级相同的进程,再判断 先来先服务。
-
短作业优先: 选择运行时间最短的
对队列中评估执行时间,选择最短的那个执行。
对执行时间短的作业或进程有利,对长的不利。长的可能会产生饥饿现象。
-
优先级调度: 选择优先级最高的
优先级用于描述作业或进程需要运行的紧急程度。
有抢占式、也有非抢占式的实现。
-
高响应比优先: 兼顾等待时间 和 要求服务的时间
主要用于作业调度。
结合了 先来先服务 和 短作业优先。
响应比: (等待时间 + 要求服务的时间) / 要求服务的时间 。
- 等待时间相同的,服务时间短的优先。 (短作业优先)
- 服务时间相同的,等待时间长的优先。 (先来先服务)
-
时间片轮转: 从就绪队列头开始,依次选择每个进程,每次仅能运行一个时间片。
主要用于分时系统。
运行进程时,如果时间片完了,该进程还没运行完,该进程就退到就绪队列的尾部。
如果时间片够大,没次进程都能运行完,就退化成了先来先服务。
-
多级反馈队列:时间片轮转和优先级调度的结合。
实现思想:(动态调整 时间片 和 优先级)
有多个就绪队列,优先级依次降低,时间片依次倍增。
进来一个进程,放到第一级队列的末尾,按 先来先服务执行。
到他了,如果执行完了,就完了。如果没有执行完,就到下一级队列的末尾,再按先来先服务。
只有当上一级队列里 的进程为空时,才能执行下一级队列里的进程。
切换进程的实现:
在切换前要 保存好当时的现场信息,以后再切换回来时,可以找得到原来信息,接着上次的情况继续执行。
这个 现场信息 就保存在 内核里面的堆栈中,在内核里还要维护这个堆栈指针。