进程与调度 · 操作系统
一个 CPU 怎么「同时」运行几十个程序?
课程目录为什么需要它
你的笔记本只有几个 CPU 核心,却同时跑着浏览器、音乐和编辑器。操作系统的调度器每秒在进程之间切换很多次,让每个进程都有进展。它怎么做选择,解释了为什么繁忙的机器会变卡,也解释了分析服务器性能时「CPU 密集」和「等待 I/O」是什么意思。
直觉理解
进程是一个正在运行的程序,有自己的内存。任何时刻它都处于某个状态:
- 运行:正在 CPU 上
- 就绪:可以运行,在等轮到自己
- 阻塞:在等某个慢的东西(磁盘、网络、按键)
轮转调度给每个就绪进程一小段时间片,用完就排到队尾。短任务很快完成,谁也不会饿死。切换本身要花一点时间(上下文切换),所以时间片不能太小。
定义
进程 Process
A running program: its code, its own memory, open files and a state (running, ready, blocked). Identified by a PID.正在运行的程序:它的代码、独立的内存、打开的文件,以及一个状态(运行、就绪、阻塞)。用 PID 标识。
上下文切换
Saving one process's CPU state and loading another's so it can continue. Necessary for sharing, but pure overhead.保存一个进程的 CPU 状态、载入另一个进程的状态,让它继续运行。共享 CPU 必须这样做,但它本身是纯开销。
示例
一步一步看轮转调度
动手试试三个任务分别需要 5、2、3 个单位的 CPU 时间。每次轮到最多给 2 个单位。
from collections import deque
ready = deque([("A", 5), ("B", 2), ("C", 3)])
quantum, clock = 2, 0
while ready:
name, left = ready.popleft()
run = min(quantum, left)
clock += run
if left - run > 0:
ready.append((name, left - run))
else:
print(name, "done at", clock)- L7运行一个时间片;如果任务先做完,就用不满。
- L10没做完:排到队尾。
- L12B 最先完成,在 4;然后 C 在 9,A 在 10。
B done at 4
常见错误
进程越多越快
4 个核心上跑 400 个吃 CPU 的进程,并不会快 100 倍;它们只是轮流跑,切换还增加了开销。
忙等
不停检查 while not ready: pass 的循环什么都没做,却占满一个 CPU。阻塞式调用能让操作系统去运行别的东西。
小测验
1. 一个进程在等磁盘读文件。它处于什么状态?
查看答案
答案:A
数据到达之前它用不了 CPU,所以调度器会跳过它。
2. 这段代码会输出什么?
jobs = [("A", 3), ("B", 1), ("C", 2)]
clock = 0
for name, need in sorted(jobs, key=lambda j: j[1]):
clock += need
print(name, clock)查看答案
答案:A
短作业优先:B(1)、C(1 + 2 = 3)、A(3 + 3 = 6)。
动手练习
3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。
- 预测输出跟踪调度器
准确写出这段程序的输出。
- 改需求用上时间片
finish_times(jobs, quantum)应该模拟轮转调度,返回每个任务完成时刻的字典。现在它让每个任务一口气跑完(先来先服务)。改成每轮最多运行quantum个单位,没做完的排到队尾。 - 从零写平均等待时间
所有任务都在时刻 0 到达,按给定顺序一个接一个运行。一个任务的等待时间是它开始之前等了多久。写函数
avg_wait(bursts),返回平均等待时间(浮点数)。然后在编辑器里用同样的任务、两种顺序试一试,看看为什么短作业优先有好处。
本课术语
| 术语 | 中文 | 英文定义 |
|---|---|---|
| Process | 进程 | A running program with its own memory and state. |
| Scheduler | 调度器 | The part of the OS that decides which process runs next. |
| Time slice (quantum) | 时间片 | How long a process may run before the scheduler switches. |