操作系统CPU调度:概念、算法与设计权衡

本文从工程实践的角度系统介绍操作系统中的CPU调度机制,包括调度目标与约束、经典调度算法(如先来先服务、最短作业优先、优先级调度和时间片轮转)、 多级队列与多级反馈队列调度,以及多核和实时系统中的调度问题。内容强调在吞吐量、响应时间、公平性和实现复杂度之间进行权衡的思路。

1FCFSSJF、优先级和时间片轮转等调度算法的平均等待时间示意对比(示意)。

2:不同调度策略下平均周转时间的示意比较(示意)。

3FCFS、时间片轮转和多级队列调度下CPU利用率变化曲线示意(示意)。

调度算法

核心思想

优点

局限

先来先服务(FCFS

按到达顺序依次运行,非抢占。

实现简单,对到达顺序较公平。

容易出现“车队效应”,对长短作业混合场景不友好。

最短作业优先(SJF

选择估计CPU运行时间最短的进程。

在理想条件下可最小化平均等待时间。

需要预测运行时间,长作业可能长期得不到调度。

优先级调度

选择优先级最高的进程运行。

可按重要程度或业务类型区分对待。

低优先级进程可能饥饿,需配合老化等机制。

时间片轮转(RR

每个进程按固定时间片循环轮流获得CPU。

响应性好,适合分时和交互系统。

性能高度依赖时间片设置,频繁切换带来开销。

多级队列调度

为不同类型进程设置多个就绪队列。

可对前台/后台等不同业务采用不同策略。

参数和队列之间的交互较复杂,需要精心调优。

多级反馈队列调度

根据进程行为在队列之间动态迁移并进行老化。

能自适应不同进程特性,减轻饥饿现象。

参数众多、分析难度大,对实现和维护提出挑战。

表1:经典CPU调度算法的核心思想、优点与局限。

指标

定义

意义

说明

CPU利用率

CPU处于工作状态的时间占比。

反映CPU资源使用效率。

过低浪费资源,过高可能缺乏空闲缓冲。

吞吐量

单位时间内完成的进程数量。

体现系统整体处理能力。

与作业类型和调度开销密切相关。

等待时间

进程在就绪队列中等待的总时间。

直接影响用户对系统响应的感知。

在理论假设下SJF可最小化平均等待时间。

周转时间

进程从提交到完成所经历的总时间。

对批处理作业和整体用户体验很重要。

包含等待、运行及I/O等各阶段时间。

响应时间

从提交到得到首次响应的时间。

对交互式和实时应用至关重要。

时间片轮转等抢占式策略旨在降低响应时间。

表2:评估CPU调度性能的主要指标。

场景

典型目标

常用算法

备注

批处理系统

提高吞吐量和CPU利用率。

FCFS、SJF、基于优先级的调度。

用户交互较少,周转时间通常比响应时间更重要。

交互式/分时系统

为大量用户提供较低响应时间。

时间片轮转、多级反馈队列。

普遍采用抢占和较小时间片。

实时系统

满足截止时间和时序约束。

速率单调(RM)、最早截止时间优先(EDF)。

强调可预测性和可调度性分析。

多核和多处理器系统

在多个核之间平衡负载并利用并行性。

负载均衡、亲和性调度、成组调度。

缓存亲和性和迁移成本是重要考虑因素。

表3:典型工作场景及对应的调度策略选择示意。

1. CPU调度的目标与约束

CPU调度负责在就绪队列中的多个进程或线程之间选择下一步获得CPU的实体,是操作系统实现并发和共享的核心机制之一。 合理的调度策略需要在提高CPU利用率和吞吐量、降低等待和响应时间以及保持不同用户和进程之间的公平性之间进行权衡。

在实际系统中,这些目标往往相互冲突。例如,为了提高吞吐量,可能更倾向于长时间运行批处理作业;而为了降低响应时间,则需要频繁抢占以照顾大量短交互任务。 调度策略的设计必须结合具体负载特性、硬件结构(单核、多核、NUMA等)以及实时或低时延应用的需求。

2. 非抢占式调度:FCFS和SJF

非抢占式调度策略允许运行中的进程一直占用CPU,直到其主动放弃(如进行I/O或结束)。先来先服务(FCFS)是最简单的非抢占策略:进程按到达顺序依次执行。 FCFS实现简单且容易理解,但在长短作业混合场景下容易出现“车队效应”,即大量短作业被一个长作业阻塞,从而降低整体响应性。

最短作业优先(SJF)通过优先选择估计运行时间最短的进程来降低平均等待时间。在理想情况下,如果能准确获得CPU运行时间预测,SJF在平均等待时间意义下是最优的。 然而在实际系统中,运行时间预测往往不准确,且长作业在高负载下可能长期得不到调度,需要配合老化或优先级调整机制缓解饥饿问题。

3. 抢占式调度和时间片轮转

抢占式调度允许操作系统通过时钟中断等手段强制中断正在运行的进程,将CPU切换给另一个就绪进程。时间片轮转(RR)是典型的抢占式策略,系统为每个进程分配固定的时间片, 时间片用尽后进程被抢占并重新排到就绪队列尾部。这样所有可运行进程都能在较短时间内获得CPU,适合交互式和分时系统。

时间片长度的选择十分关键。时间片过大时,RR趋近于FCFS,响应性下降;时间片过小时,则频繁的上下文切换会增加开销并影响吞吐量。 因此,操作系统通常根据典型CPU运行时间分布和硬件特性对时间片大小进行调优。

4. 优先级调度

优先级调度为每个进程分配一个优先级,调度器选择优先级最高的就绪进程运行。优先级可以反映用户类别、业务重要程度或资源使用模式等。 在实时系统中,优先级往往用于表示任务的时序关键性,既可以采用抢占式也可以采用非抢占式变体。

单纯优先级调度容易导致低优先级进程饥饿,尤其在高优先级任务持续繁忙的情况下。为缓解这一问题,系统通常采用老化策略,随着等待时间增长逐步提升进程优先级, 或根据观察到的行为动态调整优先级,以在长期尺度上实现一定的公平性。

5. 多级队列与多级反馈队列

多级队列调度将就绪队列划分为多个队列,每个队列对应一种进程类别,如前台交互任务、后台批处理作业或系统服务等, 不同队列可以采用不同的调度策略(例如前台使用时间片轮转,后台使用FCFS),调度器再根据预设规则在各队列之间分配CPU时间。

多级反馈队列在多级队列基础上允许进程在队列之间动态迁移,根据进程是否CPU密集或I/O密集、是否长期等待等特征进行反馈调整。 这样可以在一定程度上缓解饥饿问题,并更好适应混合负载场景,但也显著增加了参数数量和系统分析难度,需要谨慎设计和调试。

6. 实时系统中的调度

在实时操作系统中,调度目标不仅包括传统的性能指标,还强调满足任务的截止时间和时序约束。硬实时任务必须严格按期完成,软实时任务则允许少量截止时间违约但仍希望尽量及时。

经典实时调度算法包括速率单调(Rate-Monotonic,RM)调度和最早截止时间优先(Earliest-Deadline-First,EDF)调度。RM根据任务周期分配固定优先级,EDF则始终调度截止时间最临近的任务。 通过可调度性分析,可以判断一组实时任务在给定调度策略和参数下是否能够满足所有截止时间,这在汽车电子、航空航天和工业控制等安全关键领域尤为重要。

7. 多核与多处理器调度

在多核或多处理器系统中,调度器不仅要决定“谁运行”,还要决定“在哪个核上运行”。负载均衡是关键问题,避免某些核空闲而其他核过载的情况,同时还要考虑进程迁移带来的缓存和NUMA开销。

常见做法包括全局和每核就绪队列相结合的设计,周期性负载重分布,以及利用亲和性信息尽量让进程在其工作集已缓存的核心上继续运行。对于紧密耦合的并行应用,成组调度或协同调度可以帮助多个线程同步执行,提高并行效率。

8. 实际系统中的调度器与调优

现实操作系统中的调度器(如Linux中的CFS等)在经典算法基础上加入了大量工程机制,如虚拟运行时间记账、优先级带、调度组等。通过这些机制,调度器在不同场景下提供相对公平的CPU分配,并兼顾交互延迟和吞吐。

系统工程师可以通过调整时间片大小、优先级范围、实时调度参数和亲和性设置,针对特定部署环境(如高吞吐服务器、低时延交易平台或混合交互/批处理集群)进行调优,以取得更好的综合效果。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐