Appearance
题目
异常事件在当前指令执行过程中进行检测,中断请求则在当前指令执行后进行检测。下列事件中,相应处理程序执行后,必须回到当前指令重新执行的是( )。
错因
A
系统调用是自陷(trap / syscall),本身是用户主动发出"请系统帮忙"的请求——syscall 指令一旦执行就已经完成它的使命,处理程序结束后接着执行下一条指令,不是重新执行 syscall 本身(否则就死循环了)。把系统调用当成"被中断重做"是混淆了自陷与故障。
C
DMA 传送结束属于 I/O 完成中断——这是外部异步中断,和当前指令在"做什么"完全无关(CPU 这一周期可能在算 ALU、可能在取下一条指令,都跟 DMA 无关)。处理完中断只需回到被打断的那条指令的下一条继续执行,不需要重做。
D
打印机缺纸属于 I/O 异常中断——同样是外部异步信号,与当前指令的执行内容无关。处理程序通知操作系统、由操作系统提示用户加纸,恢复后从被打断的下一条指令继续。"重新执行当前指令"对外部中断没有意义。
总解析
核心区分:异常 / 中断按"恢复方式"分三类:
| 类别 | 触发时机 | 处理后从哪儿继续 | 例子 |
|---|---|---|---|
| 故障(fault) | 当前指令执行中检测 | 回到当前指令重新执行 | 缺页、保护异常、未定义指令 |
| 陷入(trap) | 当前指令执行完主动触发 | 下一条指令 | 系统调用、int 80、断点 |
| 终止(abort) | 严重错误 | 终止程序,不返回 | 硬件错误 |
| 外部中断 | 与指令异步、当前指令执行完检测 | 下一条指令 | DMA 完成、打印机缺纸、键盘 |
逐项判断:
| 选项 | 类别 | 处理后回到 | 是否"重新执行当前指令" |
|---|---|---|---|
| A. 系统调用 | 陷入(trap) | 下一条 | ✗ |
| B. 页缺失 | 故障(fault) | 当前指令 | ✓ |
| C. DMA 传送结束 | 外部中断 | 下一条 | ✗ |
| D. 打印机缺纸 | 外部中断 | 下一条 | ✗ |
为什么页缺失必须重新执行当前指令:
页缺失发生在内存访问的中途——指令还没"完成访问"就被异常打断。处理程序(OS 缺页处理)从磁盘把页调入内存、更新页表后,原先那次访问的物理地址才有效。所以必须回到这条指令的开头重新执行,让取数 / 取指过程在新页表下重新走一次,才能拿到正确的数据。
如果只跳到"下一条指令",那条 load/store 永远没真正完成,结果就是错的。
最终答案是 B(页缺失)。
记忆口诀:
- "故障回当前"(fault → re-execute):缺页、保护、除零、地址越界
- "陷入走下一条"(trap → next instr):系统调用、断点、
int n - "中断也走下一条"(external → next instr):所有 I/O 完成 / 外设事件
只有"故障"类需要回到当前指令重新执行。