整理自 MIT OCW 6.004 Computation Structures(Spring 2017)L18 注解幻灯片。
源网页:18.1 Annotated Slides | Devices and Interrupts
讲师:Chris Terman。图片直接引用 OCW 原站链接。
L18:设备与中断(Devices and Interrupts)
本讲讲 OS 如何用 interrupt 与内核缓冲对接 I/O,以及 blocking SVC(ReadKey)在中断禁用下的实现演进(忙等 → 重试 SVC → Scheduler → sleep/wakeup);后半转入 hard real-time:latency、weak/strong priority、周期性负载与截止期可满足性。
1. OS 组织:I/O 设备(OS Organization: I/O Devices)
OS 与外设交互分两层:
- 设备侧:interrupt handler + 内核缓冲,把数据搬进/搬出设备
- 用户侧:supervisor call(SVC)按用户进程请求访问这些缓冲
难点:SVC 发出时请求未必立刻能完成(缓冲空/满),需要阻塞与唤醒机制。
2. 异步 I/O 处理(Asynchronous I/O Handling)
流程:按键 → 键盘触发 interrupt → 暂停当前进程 → handler 读字符写入拥有键盘焦点进程的内核缓冲 → 恢复被中断进程。人打字远慢于指令执行,及时服务即可跟上。
缓冲满时:覆盖旧字符无意义,通常丢弃新字符并蜂鸣提示。稍后用户程序调用 ReadKey() SVC,OS 从缓冲取字符放入用户 R0。
- blocking I/O:返回时 R0 必有字符;尚无则阻塞
- non-blocking I/O:立即返回状态标志 + 结果,程序自行决定是否稍后重试
3. 基于中断的异步 I/O(Interrupt-based Asynch I/O)
用户程序不轮询键盘,而是 event-driven:设备需要服务时用 interrupt 通知 OS。职责分离优雅——有活才占 CPU,对用户程序透明。
设备访问两种常见方式:
- 专用 I/O 指令(如实验 Beta 的
RDCHAR()、CLICK()) - memory-mapped I/O:内核地址空间一段映射到设备寄存器,用普通 LD/ST 访问
示意代码用 MMIO:结构体含 status 与 data;handler 读键码写入环形缓冲。实际还要处理 press/release、Shift/Ctrl、CTRL-ALT-DEL 等特殊组合,以及 raw vs cooked 输入模式。
4. ReadKey SVC:尝试 #1(ReadKey SVC: Attempt #1)
ReadKey() 的 opcode 非法 → 异常进入 OS → 识别为 SVC 再分派子 handler。缓冲非空:从进程表找到对应键盘缓冲,字符写入保存的用户 R0,退出后恢复寄存器。
缓冲空时若在 handler 内 while 空转等待:SVC 在 supervisor 模式(PC[31]=1)运行,中断被禁用 → 键盘 interrupt 永远进不来 → 死循环,系统假死。失败。
5. ReadKey SVC:尝试 #2(ReadKey SVC: Attempt #2)
修复:返回前把保存的 XP 减 4。异常时 XP 存的是非法指令的 PC+4;正常 JMP(XP) 会执行 SVC 之后的指令。XP−4 使恢复后重新执行同一条 SVC。
关键差别:重试时有一拍在 user-mode(PC[31]=0)执行,此时若有挂起键盘 interrupt,可抢占并填满缓冲;再进 SVC 就能取到字符。能工作,但空缓冲时忙等重试,浪费 CPU,直到 timer 切到别的进程。
6. ReadKey SVC:尝试 #3(ReadKey SVC: Attempt #3)
空缓冲时:安排重试 SVC 后立刻调用 Scheduler(),主动让出时间片。轮转调度回来再试。代价是打字后重启略有延迟,但时间片通常短于击键间隔,不明显。
对照 timesharing 质疑:10 个各需 1s 的作业,无分时依次完成;有分时则几乎都在 ~10s 后才完——最坏完成时间不更短。但若多数进程在等 I/O,分时把空闲周期送给能干活的进程,整体利用率更好。真实系统里大量进程处于 I/O wait。
7. 更精细的调度(Sophisticated Scheduling)
进程状态加 status:ACTIVE(0)或 WAITING(非零,不同值表示等不同事件)。Scheduler() 只跑 ACTIVE。UNIX 风格原语:sleep(event) / wakeup(event),参数即 status 标识。
8. ReadKey SVC:尝试 #4(ReadKey SVC: Attempt #4)
缓冲空 → sleep(kbdnum) 设 WAITING 并调度;键盘 handler 写入缓冲后 wakeup(kbdnum),把所有等该事件的进程标为 ACTIVE。睡着的进程在事件发生前完全不占 CPU——优雅且高效。
9. 例题:Handler 与 OS 配对(Example: Match Handler to OS)
三种 ReadKey 变体 R1/R2/R3,三种系统 Model A/B/C:
- R1(似尝试 #2,但总读键盘 0):只适合单进程 Model C(分时下会串共享输入)
- R2(似尝试 #1 的 while 空转):只适合 Model B(SVC 内仍允许设备中断)
- R3(尝试 #3):配对标准 Model A(内核不可中断)
10. 哪套 Handler 与 OS?#1(Which Handler and OS? #1)
用户报:“编译错误,Scheduler 与 ProcTbl 未定义。” → 非分时系统无这两符号;R2 也不调用 Scheduler → R3 跑在 Model C。
11. 哪套 Handler 与 OS?#2(Which Handler and OS? #2)
“现在总从键盘 0 读所有人输入,而且更浪费 CPU。” → 只有 R1 固定键盘 0;相对旧 handler 明显更费说明以前不是忙等的 R2 → R1 在 Model A。
12. 哪套 Handler 与 OS?#3(Which Handler and OS? #3)
“新系统工作正常,还更省 CPU!” → 排除 R1 在分时(共享键盘可察觉)、R2/R3 在无进程表的 C、R2 在不可中断内核 A → Model B 用户现跑 R3。
13. 对“实时”的需求(The Need for “Real Time”)
分时给每进程独立虚拟机的错觉,利用率好,但无法保证完成时间——取决于其他进程占用。OS 把 interrupt 事件暂存与用户态处理(经 SVC)分离,更难保证在 deadline 前处理完。
汽车 ESC(电子稳定控制)等控制系统有硬截止期:测力/转向/轮速 → 判是否失控 → 单轮制动纠正航向。错过截止期可能危及安全。
14. 中断延迟(Interrupt Latency)
Interrupt latency :从请求运行某代码到代码真正开始执行的时间。服务时间 、截止期 时,最大允许延迟满足 。必须始终 的约束称 hard real-time constraints。
15. 延迟来源(Sources of Interrupt Latency)
贡献因素:保存进程状态、切内核、分派 handler;不可中断的长时段(复杂多周期指令如 block move——ISA 应可中断重启);以及已在内核处理另一 interrupt(中断禁用)时的等待。
目标:界住并最小化 ——优化取中断路径、避免数据相关长指令、缩短内核态时间;必要时允许内核内仍可被更高优先级中断。
16. 多设备调度(Scheduling of Multiple Devices)
三设备服务时间:键盘 800 µs、磁盘 500 µs、打印机 400 µs。请求稀少、任意到达。FCFS 下最坏延迟 = 另两设备服务之和:键盘 900、磁盘 1200、打印机 1300 µs。长 handler 拖累他人——有无更好调度?
17. 弱(非抢占)优先级(Weak (Non-preemptive) Priorities)
Weak / nonpreemptive priority:当前任务跑完才按优先级选下一个;新到的更高优先级也不能打断。最坏延迟 ≈ 任意其他设备最长服务时间 + 所有更高优先级服务时间。
例:优先级 磁盘 > 打印机 > 键盘 → 键盘仍 900;磁盘只需等当前最长者(键盘)→ 800 µs;打印机最坏 800+500=1300 µs。
18. 设定优先级(Setting Priorities)
硬实时下:Earliest Deadline——按截止期排序,越早截止优先级越高。若存在能满足所有截止期的优先级赋值,EDF 也能满足。机场安检先办最早航班的比喻。过载时最小化“误机人数”则更复杂,超出本讲范围。
默认:未另行规定时, 取为到同一设备下一次请求的时间,避免系统越落越远。
19. 需要抢占(The Need for Preemption)
弱优先级下最坏延迟总含“当前最长其他任务”。若磁盘截止期 800 µs、 → 允许 µs,但弱优先级只能保证 800 µs → 不够。
引入 strong / preemptive priority:高优先级可打断低优先级 handler。同优先级序下:磁盘 ,打印机 500,键盘仍 900——磁盘截止期可满足。
20. 强优先级实现(Strong Priority Implementation)
Beta 改造:PC[31] 单比特 supervisor 改为 PC[31:29] 的 3-bit PRI(8 级)。设备请求带自己的优先级 ;优先级编码器选出最高请求,仅当 才接受中断。接受后旧 PC+PRI 存入 XP,新 PRI 设为 。高优先级最坏延迟不再受低优先级服务时间影响。
21. 重复中断(Recurring Interrupts)
加上最大请求频率:打印机每 1 ms、磁盘 2 ms、键盘 10 ms。强优先级下磁盘立即服务、打印机可抢占键盘。键盘开始延迟仍可 ≤900 µs,但不断被抢占,完成可能晚到请求后 3 ms——说明实时约束应用 deadline 表达,而非仅看 latency。周期需求过紧时 CPU 周期根本不够。
22. 中断负载(Interrupt Load)
周期负载:键盘 ,磁盘 25%,打印机 40%,合计 73%,剩 27% 给用户态。总负载 >100% 必失败。
截止期窗口内还要为更高优先级留预算:磁盘需 ;打印机有效截止 1000 µs 内需 500+400=900 µs。键盘若 µs 需 500+2×400+800=2100 > 2000 → 不可行; 时 2×500+3×400+800=3000 → 刚好。
23. Mr. Blue 访问 ISS(Mr. Blue Visits the ISS)
国际空间站三任务 SSG / G / CP;先分析 弱优先级:
- CP 最大服务时间:G 的 ms → 任何其他 handler ≤10 ms
- EDF 序:G > SSG > CP
- 负载:SSG 5/30≈16.7%,G 25%,CP 10% → 合计 ~51.7%,空闲 ~48.3%
- 最坏完成:SSG 等 CP+G 再加自身 → 25 ms;G 等 CP+自身 → 20 ms;CP 等 SSG+G+自身 → 25 ms
24. Mr. Blue 访问 ISS(续)(Mr. Blue Visits the ISS (cont’d.))
改 强优先级(同序 G > SSG > CP):
- CP 可被抢占 → 不再受高优先级 限制;100 ms 窗口内最多 4 次 SSG + 3 次 G = 50 ms,故 CP 服务可达 50 ms
- CP 占 50% + 其余 → 总约 91.7%,空闲 ~8.3%
- 最坏完成:G = 自身服务时间;SSG ≤ 一次 G + 自身 = 15 ms;CP 按设计刚好压在 100 ms 截止期
25. 小结(Summary)
- 用户与设备交互拆成:设备侧 interrupt + 内核缓冲;应用侧 SVC
- 阻塞 I/O:经 XP−4 重试、Scheduler、最终 sleep/wakeup,避免空转
- Hard real-time:latency、service time、deadline;weak vs strong priority
- 实践中常多级强优先级,同级内再用弱优先级仲裁——足以应对多数 I/O 实时约束