115 / 163 · C11 · 约 8 分钟
CPU虚拟化的总结对话
先记住这句话
本对话回顾操作系统如何通过硬件机制与谨慎策略实现CPU虚拟化,强调控制权保持、调度权衡以及实际系统中的工程现实。
实现处理器共享的关键硬件机制
多个程序要共用同一颗CPU,操作系统必须依赖陷阱、特权级切换和周期性定时器。硬件在异常或中断时自动保存关键状态并进入内核,操作系统再完成完整上下文的保存与恢复,让被暂停的程序能从精确位置继续。没有这些机制,任何用户程序都可能永久霸占处理器。
有限直接执行与操作系统的控制欲
为了速度,操作系统让用户代码在硬件上原生运行,同时通过用户/内核模式和定时检查随时能夺回控制。这种设计既追求效率,又对错误或恶意程序保持高度警惕,使操作系统始终扮演资源管理者的角色。
调度策略的内在冲突
把短任务提前能改善周转时间,时间片轮转能改善交互响应。多层反馈队列试图同时接近这两种目标,但指标彼此对立,因此不存在对所有负载都最优的算法。务实的工程师更关注如何避开灾难性结果,而不是寻找理论上的完美方案。
从课堂到云端的实际启示
掌握这些内部细节有助于在共享云环境中合理安排作业或诊断延迟。同时也提醒我们调度器可能被策略性利用,因此真实系统必须考虑对抗性行为,而不能假设所有用户都善意合作。
常见误区
- 以为合作进程会主动让出CPU,从而忽略强制定时器的必要性。
- 把时间片设得过短却未计入上下文切换的真实开销。
- 相信存在一种对所有工作负载都最优的调度算法。
运行一个例子
最低标准 C11 · 完整程序 · 下载 .c
#include <stdio.h>
int main(void) {
int t;
const char *jobs[2] = {"ProcA", "ProcB"};
int cur = 0;
for (t = 0; t < 8; t++) {
printf("[%d] executing %s\n", t, jobs[cur]);
if ((t + 1) % 3 == 0) {
printf(" * timer fires, context switch from %s\n", jobs[cur]);
cur = 1 - cur;
printf(" * resume %s\n", jobs[cur]);
}
}
return 0;
}
在本地编译
gcc -std=c11 -Wall -Wextra -Wpedantic -Werror ostep-11-cpu-summary.c -o example && ./example预期结果
[0] executing ProcA
[1] executing ProcA
[2] executing ProcA
* timer fires, context switch from ProcA
* resume ProcB
[3] executing ProcB
[4] executing ProcB
[5] executing ProcB
* timer fires, context switch from ProcB
* resume ProcA
[6] executing ProcA
[7] executing ProcA
CHECK YOUR UNDERSTANDING
合上答案,试着解释。
即便每个进程都通过系统调用与内核合作,为什么操作系统仍然必须使用定时器中断?
查看参考答案
恶意或有缺陷的程序可能永远不发起系统调用;定时器保证内核能在有界时间内重新获得控制权。
继续查证
标准草案与官方章节会更新;版本标记只说明示例最低要求。