CPU Scheduling Timing And Dispatch
调度时机
低级调度从就绪队列中选择一个进程,为它分配 CPU。
需要进行进程调度与切换的情况,可以分成两类。
| 类型 | 触发情况 | 含义 |
|---|---|---|
| 当前进程主动放弃 CPU | 正常终止 | 进程执行结束,不再需要 CPU |
| 当前进程主动放弃 CPU | 异常终止 | 运行中发生错误,被迫结束 |
| 当前进程主动放弃 CPU | 主动阻塞 | 请求 I/O、等待资源或事件,暂时无法继续运行 |
| 当前进程被动放弃 CPU | 时间片用完 | 分时系统用时钟中断周期性收回 CPU |
| 当前进程被动放弃 CPU | 有更紧急事件需要处理 | 例如 I/O 中断到达 |
| 当前进程被动放弃 CPU | 更高优先级进程进入就绪队列 | 抢占式调度下,当前进程可能被暂停 |
主动放弃 CPU 时,当前进程自己已经无法或不需要继续运行。被动放弃 CPU 时,当前进程本来还可以继续执行,但系统为了响应性、公平性或优先级,强行收回 CPU。
不能调度和不能抢占的情况
有些位置即使出现了调度条件,也不能立刻切换进程。
| 情况 | 为什么不能立刻切换 |
|---|---|
| 正在处理中断 | 中断处理过程与硬件状态密切相关,通常要先完成中断处理,再到安全点决定是否调度 |
| 正在操作系统内核程序临界区 | 内核可能正在访问就绪队列、PCB 队列等关键数据结构,切换会破坏内核管理数据的一致性 |
| 正在执行原语 | 原语必须原子完成,不能在中途被打断 |
内核临界区和普通临界区不同
进程处于普通临界区时,不一定禁止处理机调度。比如进程正在使用打印机,打印机是慢速设备,如果一直不允许调度,CPU 可能长期空闲。
不能调度的是操作系统内核程序临界区。这类临界区访问的是内核管理数据,例如就绪队列、阻塞队列、PCB 链表。若这些结构还没维护完就切换,会让后续调度、唤醒、阻塞等操作读到不一致状态。
调度方式
进程调度方式按是否允许强行收回 CPU,可分为非抢占式和抢占式。
| 调度方式 | 也称 | 规则 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|---|
| 非抢占式调度 | 非剥夺调度 | 只允许进程主动放弃 CPU | 实现简单,系统开销小 | 不能及时处理紧急任务 | 早期批处理系统 |
| 抢占式调度 | 剥夺调度 | 更重要或更紧急的进程到达时,可以暂停当前进程 | 响应快,可实现时间片轮转和实时响应 | 切换开销更大,需要更复杂的保护机制 | 分时系统、实时系统 |
非抢占式系统中,运行进程阻塞或退出时才触发调度。抢占式系统中,每个时钟中断或若干个时钟中断都可能触发调度程序工作。
分派器
调度器和分派器不是同一件事。
调度器 scheduler 负责做选择:
- 让谁运行。
- 按什么调度算法选择。
- 在时间片轮转等策略中,运行多长时间。
分派器 dispatcher 负责把 CPU 真正交给被选中的进程:
- 保存当前进程的处理机现场。
- 恢复新进程的处理机现场。
- 切换到新进程的地址空间和内核栈等运行环境。
- 让 CPU 从新进程上次停下的位置继续执行。
可以这样区分:
- 狭义的进程调度:只指从就绪队列中选中一个进程。
- 进程切换:一个进程让出 CPU,由另一个进程占用 CPU。
- 广义的进程调度:选择进程 + 进程切换。
进程切换过程
进程切换主要完成两类动作:
- 保存原来运行进程的各种数据。
- 恢复新进程的各种数据。
这些数据包括程序计数器 PC、程序状态字 PSW、通用寄存器、栈指针等处理机现场信息。它们通常保存在 PCB 中。
一次典型切换可以按以下顺序理解:
- 当前进程因为时间片用完、阻塞、终止或被抢占而离开运行态。
- 内核保存当前进程的 CPU 现场到该进程 PCB。
- 内核修改当前进程状态,并把 PCB 放入合适队列。
- 调度器从就绪队列选择下一个进程。
- 分派器从新进程 PCB 恢复 CPU 现场。
- 新进程进入运行态,从保存的 PC 位置继续执行。
进程切换有代价。调度和切换过于频繁时,系统会把大量时间花在保存、恢复现场和维护队列上,真正用于执行用户进程的时间反而减少。
闲逛进程
当没有其他就绪进程时,调度程序会选择闲逛进程,即 idle process。
闲逛进程的特点:
- 优先级最低。
- 只有没有其他就绪进程时才运行。
- 可以设计为能耗较低的循环或特殊指令序列。
- 它占用 CPU 的目的不是完成用户任务,而是让 CPU 在无事可做时保持一个可控状态,并在指令周期末尾继续检查中断。
闲逛进程的存在说明:CPU 在操作系统管理下通常总运行着一个进程。没有用户进程可运行时,就是 idle。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Elian's blog page!