调度的目标
这一节给出的是度量工具。下一节的所有算法之所以有优劣之分,全靠这几个指标来评判;而计算题的分数,也几乎全部落在这几个公式上。
指标一共五个,其中周转时间和带权周转时间是绝对主力。
机制
五个指标
CPU 利用率
系统吞吐量
周转时间——这是最重要的一个。
带权周转时间
由定义可知 带权周转时间恒 ≥ 1。等于 1 意味着作业一提交就立即独占 CPU 跑完,中间零等待。这是一个很好用的自检点:如果算出来小于 1,一定是算错了。
等待时间
这里有一个范围限定必须留意:对”进程”而言,等待时间不包括等待 I/O 的时间——因为进程等 I/O 时并不需要 CPU 服务,调度算法对此无能为力;而对”作业”而言,还要额外加上它在外存后备队列上等待作业调度的那段时间。
响应时间
指标之间是互相冲突的
一个必须建立的认识是:不存在在所有指标上都最优的算法。
追求吞吐量和平均周转时间,就应该让短作业先跑(SJF 类算法),但这必然让长作业等待更久,甚至饥饿。
追求响应时间,就应该频繁轮转(RR),但每次切换都有上下文切换开销,时间片越小切换越频繁,CPU 利用率反而下降。
追求公平,就不能总照顾短作业,那么平均周转时间必然变差。
所以选择算法的实质,是根据系统类型决定牺牲哪个指标。批处理系统愿意牺牲响应时间换吞吐量;分时系统愿意牺牲平均周转时间换响应时间;实时系统连平均值都不在乎,只在乎最坏情况。
边界
周转时间 vs 等待时间 vs 响应时间
三个”时间”极易混淆,用一条时间轴上的三个问题区分:
- 周转时间问:“从提交到全部做完,一共多久?”
- 等待时间问:“这段时间里,干等着没被服务的部分有多久?”
- 响应时间问:“从提交到第一次有反应,多久?”
关键差别在终点:周转时间的终点是完成,响应时间的终点是首次响应。一个作业可能 1 毫秒就给出首次响应,却要 10 秒才跑完。
等待时间的口径随对象而变
这是最容易失分的地方,务必按对象区分:
| 对象 | 等待时间包含什么 |
|---|---|
| 进程 | 等待处理机的时间 |
| 作业 | 等待处理机的时间 + 在外存后备队列上等待作业调度的时间 |
两者都不包含等待 I/O 的时间。 因为进程在做 I/O 时是在被”服务”,只不过服务它的是设备而非 CPU。
带权周转时间 ≥ 1 是硬约束
前面已述,这是最好用的自检点。同理,周转时间 ≥ 实际运行时间、等待时间 ≥ 0。计算题算完随手验一遍,能挡掉大部分低级错误。
对照速查
| 指标 | 公式 | 谁最在乎 |
|---|---|---|
| CPU 利用率 | 有效工作时间 / 总时间 | 所有系统 |
| 系统吞吐量 | 完成作业数 / 总时间 | 批处理 |
| 周转时间 | 完成时间 − 提交时间 | 批处理 |
| 带权周转时间 | 周转时间 / 实际运行时间(≥1) | 批处理(对短作业公平) |
| 等待时间 | 周转时间 − 实际运行时间 | 所有系统 |
| 响应时间 | 首次响应时刻 − 提交时刻 | 分时 / 交互式 |
| 想优化的目标 | 代价 |
|---|---|
| 平均周转时间 ↓ | 长作业可能饥饿 |
| 响应时间 ↓ | 切换频繁,CPU 利用率 ↓ |
| 公平性 ↑ | 平均周转时间 ↑ |
考点
- 五个公式(周转时间与带权周转时间是主力)
- 带权周转时间恒 ≥ 1,可用作自检
- 响应时间的终点是”首次响应”而非”完成”
- 等待时间不含等待 I/O 的时间;作业的等待时间还要加上外存排队时间
- 指标之间互相冲突,选择算法即选择牺牲哪一项
链接
- 🏠 返回总览:操作系统第 2 章:进程与线程总览
- ⬅️ 上一节:2.2.2 调度的实现
- ➡️ 下一节:2.2.4 进程切换
- 🔗 各算法在这些指标上的表现见 2.2.5 CPU 调度算法
- 📖 名词库:第 2 章名词库