C++ / a working model

115 / 163   ·   C11   ·   约 8 分钟

CPU虚拟化的总结对话

先记住这句话

本对话回顾操作系统如何通过硬件机制与谨慎策略实现CPU虚拟化,强调控制权保持、调度权衡以及实际系统中的工程现实。

本篇内容
  1. 实现处理器共享的关键硬件机制
  2. 有限直接执行与操作系统的控制欲
  3. 调度策略的内在冲突
  4. 从课堂到云端的实际启示
  5. 运行示例
  6. 动手练习

官方章节 PDF

实现处理器共享的关键硬件机制

多个程序要共用同一颗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

合上答案,试着解释。

即便每个进程都通过系统调用与内核合作,为什么操作系统仍然必须使用定时器中断?

查看参考答案

恶意或有缺陷的程序可能永远不发起系统调用;定时器保证内核能在有界时间内重新获得控制权。

继续查证

标准草案与官方章节会更新;版本标记只说明示例最低要求。

回到目录