[! danger] CPU 调度 $\neq$ 进程调度
CPU-Scheduling, 进程调度只是一个层级的 CPU 调度

进程调度

进程调度是调度器从就绪队列中选出下一个运行实体。它只完成“选谁”,并没有完成现场切换,也没有直接返回用户态。

一次完整的控制权交接依次经过:

  1. 中断、异常或系统调用使 CPU 进入内核态。
  2. 调度器从就绪队列中选出下一个运行实体。(即进程调度
  3. 分派器保存原现场,恢复新现场。
  4. 内核执行中断或陷入返回,才进入被选中进程的用户态代码。
Important

调度决策完成时仍在内核态。真正回到用户态的分界点,是分派完成后执行中断返回或陷入返回指令。

发生进程调度的时机

运行进程下处理机时,必须另选一个进程;新进程创建或被唤醒的进程进入就绪态时,是否发生调度取决于调度方式和优先级。

发生的事件 调度结果
正常退出或异常终止 必须选择其他就绪进程
请求 I/O、等待资源或事件而阻塞 必须选择其他就绪进程
时间片用完 抢占式系统通常把它放回就绪队列并重新选择
新进程创建完成,进入就绪态 抢占式系统可能立即改选更合适的进程
阻塞进程被唤醒,进入就绪态 抢占式系统可能立即改选更高优先级进程
中断或系统调用处理即将结束 内核在返回前检查是否需要重新调度。若被唤醒者优先级更高,抢占式调度才可能让当前进程让出 CPU。

900

不能立刻切换的情况

内核可以先记录需要调度,等到能够安全切换的位置再执行分派。

情况 为什么暂缓切换
中断处理尚未完成 要先保存或恢复必要的硬件和内核状态
正在修改调度队列等内核关键结构 中途切换可能让其他代码看到不一致数据
正在执行不可分割的内核操作 必须先完成原子更新
内核临界区和普通临界区不同

进程处于普通临界区时,不一定禁止处理机调度。比如进程正在使用打印机,打印机是慢速设备,如果一直不允许调度,CPU 可能长期空闲。

不能调度的是操作系统内核程序临界区。这类临界区访问的是内核管理数据,例如就绪队列、阻塞队列、PCB 链表。若这些结构还没维护完就切换,会让后续调度、唤醒、阻塞等操作读到不一致状态。

中断处理程序可以发现需要调度,但完整的进程切换通常要等到中断处理结束后的安全位置再执行

调度方式

进程调度方式按是否允许强行收回 CPU,可分为非抢占式和抢占式。

调度方式 也称 规则 优点 缺点 适用场景
非抢占式调度 非剥夺调度 只允许进程主动放弃 CPU 实现简单,系统开销小 不能及时处理紧急任务 早期批处理系统
抢占式调度 剥夺调度 更重要或更紧急的进程到达时,可以暂停当前进程 响应快,可实现时间片轮转和实时响应 切换开销更大,需要更复杂的保护机制 分时系统、实时系统

非抢占式系统中,运行进程阻塞或退出时才触发调度。抢占式系统中,每个时钟中断或若干个时钟中断都可能触发调度程序工作。

[! danger] 系统调用结束后不一定立即返回发起进程
发起系统调用的进程进入内核后,可能因为等待 I/O 而阻塞,也可能在系统调用完成时遇到更高优先级进程就绪。抢占式调度器可以选中其他进程,把原进程放入就绪队列。原进程以后再次获得 CPU 时,才从系统调用返回到自己的用户态代码。

分派器

调度器和分派器不是同一件事。

900

调度器 scheduler 负责做选择:

  • 让谁运行。
  • 按什么调度算法选择。
  • 在时间片轮转等策略中,运行多长时间。

分派器 dispatcher 负责把 CPU 真正交给被选中的进程:

  • 保存当前进程的处理机现场。
  • 恢复新进程的处理机现场。
  • 切换到新进程的地址空间和内核栈等运行环境。
  • 让 CPU 从新进程上次停下的位置继续执行。

可以这样区分:

  • 狭义的进程调度:只指从就绪队列中选中一个进程。
  • 进程切换:一个进程让出 CPU,由另一个进程占用 CPU。
  • 广义的进程调度:选择进程 + 进程切换。

进程切换过程

进程切换主要完成两类动作:

  1. 保存原来运行进程的各种数据。
  2. 恢复新进程的各种数据。

这些数据包括程序计数器 PC、程序状态字 PSW、通用寄存器、栈指针等处理机现场信息。它们通常保存在 PCB 中。

一次典型切换可以按以下顺序理解:

  1. 当前进程因为时间片用完、阻塞、终止或被抢占而离开运行态。
  2. 内核保存当前进程的 CPU 现场到该进程 PCB。
  3. 内核修改当前进程状态,并把 PCB 放入合适队列。
  4. 调度器从就绪队列选择下一个进程。
  5. 分派器从新进程 PCB 恢复 CPU 现场。
  6. 新进程进入运行态,从保存的 PC 位置继续执行。

进程切换有代价。调度和切换过于频繁时,系统会把大量时间花在保存、恢复现场和维护队列上,真正用于执行用户进程的时间反而减少。

闲逛进程

当没有其他就绪进程时,调度程序会选择闲逛进程,即 idle process。

闲逛进程的特点:

  • 优先级最低。
  • 只有没有其他就绪进程时才运行。
  • 可以设计为能耗较低的循环或特殊指令序列。
  • 它占用 CPU 的目的不是完成用户任务,而是让 CPU 在无事可做时保持一个可控状态,并在指令周期末尾继续检查中断。

闲逛进程的存在说明:CPU 在操作系统管理下通常总运行着一个进程。没有用户进程可运行时,就是 idle。