概述
多道程序操作系统的基础。通过在进程之间切换CPU,操作系统可以提高计算机的吞吐率。
对于单处理器系统,每次只允许一个进程运行:任何其他进程必须等待,直到CPU空闲能被调度为止。
CPU按一定的调度算法从就绪队列中选择一个进程,把CPU的使用权交给被选中的进程,如果没有就绪进程,系统会安排一个系统空闲进程或系统空闲进程。
调度触发事件:
- 创建、唤醒、退出等进程控制操作
- 进程等待I/O,I/O中断
- 时钟中断(时间片用完,计时器到时)
- 出现abort异常
调度过程
同时把多个进程导入内存,在内存中等待的就绪队列的节点是PCB,使得一个进程在CPU中执行I/O时,一个进程用来填补CPU的时间。 通常进程都是在CPU区间和I/O区间之间转换。
CPU调度程序称为短期调度程序,从内存调度到CPU。
抢占调度和非抢占调度(协作):前者为一个进程还没结束之前就被夺取CPU的拥有权,而后者则要一个进程结束或等待I/O才给予其他进程CPU的拥有权。
虽然现代操作系统都是用抢占调度,但是对于同时访问一个数据来说就会有风险,比如一个进程在试图更新一个数据,但是另一个进程抢占,并且读取这个数据,使得数据不一致。进程同步可以使数据得到安全的访问。
调度准则:
- CPU使用率。
- 吞吐量:单位时间完成进程的数量。
- 周转时间:进程提交到进程完成。即从磁盘等待进入内存+就绪队列等待时间+CPU执行时间+I/O执行时间。但是CPU调度算法只是里面的一块。
- 等待时间:在就绪队列等待的时间之和。
- 响应时间:用于交互系统。
具体步骤:
- 保存进程A的上下文环境(程序计数器,程序状态字,其他寄存器)
- 更新A的PCB(新状态和其他信息)
- 把进程A移至合适队列(就绪,阻塞,…)
- 把进程B的状态设置为运行态
- 从进程B的PCB中恢复上下文(程序计数器,程序状态字,其他寄存器)
上下文切换的开销:
- 保存和恢复寄存器
- 切换地址空间(相关指令可能比较昂贵)
- 缓存和缓冲失效(高速缓存,缓冲区缓存,TLB)
调度算法
各种调度算法:
多处理器调度:
- 需要决定在哪一个CPU上执行
- 要考虑进程在多个CPU之间迁移的开销(高速缓存失效,TLB失效),尽可能使CPU总在同一个进程上执行
要考虑负载均衡问题
- FCFS 先到先服务
一旦选定进程,那么在结束之前就不能再切换到另一个进程。 - SJF 最短优先 精确的讲是最短下一个CPU区间的算法
前面提到,一个进程是由CPU区间和I/O区间交替组成的。而SJF是看哪个进程的CPU区间最短。
- FCFS 先到先服务
- SRTF抢占式:又称最短剩余优先,当新进来的进程的CPU区间比当前执行的进程所剩的CPU区间短,则抢占。
- 非抢占:称为下一个最短优先,因为在就绪队列中选择最短CPU区间的进程放在队头。
SJF用于长期调度而不能用短期调度,因为进程是一个整体,CPU没法知道进程中第一个CPU区间长度。
SJF需要确定下一个CPU区间的时间长度,可以通过近似估算出下一个CPU区间的长度,比如tn+1=atn+(1-a)rn tn为最近最近一次的CPU时间,rn为历史记录。a是给定的权重。
- 优先级调度算法 pintos的优先级是0-63 0为最低优先级,63为最高优先级
SJF是特殊的优先级调度算法,以CPU区间长度的倒数为优先级。
(1)内部优先级:通过内部数据比如内存要求等。
(2)外部优先级:用户自己设定。set_priority
分为抢占式和非抢占式,前者为如果进来的进程优先级高于运行的进程,则替换;后者只是在就绪队列中按优先级排队。
缺点:无线阻塞或饥饿。前者为一个优先级高且运行时间长的进程一直阻塞,后者为优先级低的进程永远都得不到执行。
解决饥饿的方法是老化。通过每个时间间隔后将等待的进程优先级降低。 - 转轮法 RR算法 抢占式
用于分时系统。每个进程都占用一个时间片的时间。就绪队列为FIFO循环队列。如果一个进程的CPU区间长度小于时间片,则继续下面的进程;如果大于时间片,则中断切换到下一个进程执行。
通常时间片长度为10ms-100ms,由此需要确定时间片大小使得上下文切换次数适当少。 - 多级队列调度
根据某种性质将一个就绪队列分成不同的独立队列,如系统进程,交互进程(前台进程),交互编辑进程,批处理进程,学生进程。
每个队列都有不同的调度算法。
每个队列都有优先级,比如前台队列就比后台队列要有绝对的优先级,因此队列间的分配方法:
- 优先级调度算法 pintos的优先级是0-63 0为最低优先级,63为最高优先级
- 只有优先级高的队列为空,才能执行低优先级队列。
- 为队列分配不同权重的CPU时间,优先级高的分配时间多。
CPU调度例子
多级反馈队列调度算法(BSD 5.3)
- 设置多个就绪队列,第一级队列优先级最高
- 给不同就绪队列中的进程分配不同长度的时间片,随着优先级的降低逐渐增大
- 当第一级队列为空时,在第二级队列调度,以此类推
- 各级队列按照时间片轮转方式进行调度
- 当一个新创建进程就绪后,进入第一级队列
- 如果进程因为用完时间片而放弃CPU,则进入下一级就绪队列
- 如果进程因为阻塞而放弃CPU,则进入相应的等待队列,等待事件发生后,该进程回到原来一级就绪队列末尾(或队首)
- 若允许抢占,被抢占进程回到原来一级就绪队列末尾(或队首)
基于优先级的抢占式多任务调度(Windows)
- 调度单位是线程
- 采用基于优先级的抢占式调度,结合时间配额的调整
- 就绪线程按优先级进入相应队列
- 系统总是选择优先级最高的就绪线程运行
- 同一优先级的各线程按时间片轮转进行调度
- 多CPU系统中允许多个线程并行运行
参考资料
《操作系统概念》 第七版