1. 进程调度概述
进程调度是操作系统内核的核心职责之一,它决定了在多个可运行进程之间如何分配有限的 CPU 时间资源。调度器的设计直接影响到系统的整体性能、用户体验和资源利用率。本章节将深入剖析调度器的作用、调度层次以及核心设计目标,为后续理解 CFS 完全公平调度器奠定基础。
1.1 操作系统调度器的作用
调度器(Scheduler)是内核中负责从就绪队列中选择下一个要执行的进程,并进行上下文切换的子系统。其核心作用可以概括为:
- 资源分配:将 CPU 这一核心计算资源公平、高效地分配给多个进程。
- 多任务并发:通过快速切换进程,在单核 CPU 上营造出多任务同时运行的假象。
- 系统响应:确保交互式进程(如键盘输入、鼠标移动)能获得及时响应。
- 吞吐量优化:在单位时间内完成尽可能多的计算任务。
关键概念:调度器并不直接“运行”进程,而是决定“谁下一个运行”。实际的执行由 CPU 完成,调度器负责管理执行权的转移。
1.2 调度层次:长程、中程、短程
现代操作系统通常将调度功能划分为三个层次,分别对应进程从创建到终止的不同阶段。这三个层次在时间尺度、调度频率和决策目标上存在显著差异。
| 调度层次 | 英文名称 | 调度频率 | 主要决策 | 典型场景 |
|---|---|---|---|---|
| 长程调度 | Long-term Scheduler | 低(秒/分钟级) | 决定哪些进程被创建并进入就绪队列 | 新进程创建、系统负载控制 |
| 中程调度 | Medium-term Scheduler | 中(毫秒/秒级) | 决定进程是否被换出内存(交换) | 内存压力管理、进程挂起/恢复 |
| 短程调度 | Short-term Scheduler | 高(微秒/毫秒级) | 决定下一个由 CPU 执行的进程 | 时钟中断、进程主动让出 CPU |
重点理解:Linux 内核中的 CFS 调度器属于短程调度范畴。它运行频率极高(每秒数百到数千次),直接决定了哪个进程获得 CPU 时间片。长程和中程调度通常由内核的其他模块(如 fork 系统调用、内存管理子系统)协同完成。
1.3 调度器设计目标
调度器的设计需要在多个相互冲突的目标之间取得平衡。不同的系统类型(如桌面系统、服务器、实时系统)对各个目标的权重不同。以下是调度器设计的三大核心目标:
1.3.1 吞吐量(Throughput)
吞吐量衡量的是单位时间内系统完成的工作量。对于批处理系统,吞吐量是首要指标。调度器通过减少上下文切换开销、优化 CPU 缓存利用率来提升吞吐量。
1.3.2 响应时间(Response Time)
响应时间指从进程提交请求到获得首次响应的时间。交互式系统(如桌面、手机)对响应时间极为敏感。调度器需要优先调度 I/O 密集型进程,因为它们通常在等待用户输入。
1.3.3 公平性(Fairness)
公平性要求每个进程都能获得与其优先级或权重相匹配的 CPU 时间。CFS 调度器的核心设计哲学就是“公平”,它试图让每个进程都获得近乎相等的 CPU 时间份额。
设计权衡:吞吐量和响应时间往往相互矛盾。例如,频繁的上下文切换可以提升响应时间,但会降低吞吐量。CFS 调度器通过引入“虚拟运行时间”(vruntime)的概念,在保证公平性的前提下,兼顾了吞吐量和响应时间。
1.4 调度器设计目标对比表
下表总结了不同系统类型对调度器设计目标的侧重程度:
| 系统类型 | 吞吐量 | 响应时间 | 公平性 | 典型调度策略 |
|---|---|---|---|---|
| 批处理系统 | ★★★★★ | ★★☆☆☆ | ★★★☆☆ | FCFS、SJF |
| 交互式系统 | ★★★☆☆ | ★★★★★ | ★★★★☆ | 时间片轮转、优先级调度 |
| 实时系统 | ★★☆☆☆ | ★★★★★ | ★★☆☆☆ | EDF、RMS |
| 通用操作系统(Linux) | ★★★★☆ | ★★★★☆ | ★★★★★ | CFS(完全公平调度) |