12.3 中断服务、优先级、屏蔽与嵌套
第 12.2 节展示了处理器自动建立的 FLAGS、CS、IP 栈帧,但它还不足以保护完整程序状态。中断服务程序还可能改变前台程序希望保持一致的通用寄存器、段寄存器、设备状态和控制器状态。
保护被中断程序的状态约定
中断服务程序应有明确的保护约定(preservation contract):凡是服务程序会修改的寄存器,除非接口明确约定用它返回结果,否则都必须先保存、后恢复。典型结构如下:
isr:
PUSH AX
PUSH BX
PUSH DS
; 建立所需的段状态
; 应答或服务设备
POP DS
POP BX
POP AX
IRET寄存器按保存顺序的逆序恢复,因为栈采用后进先出规则。必须使用 IRET 而不是 RET,才能移除处理器自动建立的中断栈帧并恢复 FLAGS。若服务程序执行 STI、修改 DS 或调用其他过程,状态保护和栈深度分析也必须扩大。
缩短服务程序可以减少其他事件等待的时间。耗时计算通常可以推迟:服务程序只捕获数据或设置标志,前台代码随后再完成复杂工作。
控制下一个待处理请求
多个设备同时请求服务时,三个相关机制分别回答不同问题:
- 优先级(priority)从符合条件的请求中选出最重要的一个。
- 屏蔽(masking)让某个来源暂时失去被选择资格。
- 嵌套(nesting)允许一个服务程序被另一个已接收请求打断。
8086 进入中断时会清除 IF,因此可屏蔽中断默认不会立即嵌套。服务程序可以在保存易受影响的状态并配置好控制器后执行 STI,允许更高优先级请求抢占。每次嵌套都会在栈上增加一个自动中断帧和更多被保存寄存器。
清除 IF 这样的全局屏蔽(global mask)会在 CPU 处阻止所有 INTR 请求。控制器的逐来源屏蔽则可以阻止一个设备,同时让其他设备继续参与选择。两种机制都不能屏蔽 NMI。被屏蔽的待处理请求可能仍保存在控制器中,解除屏蔽后重新获得资格;屏蔽不一定等于删除事件。
不受控制的嵌套可能耗尽栈空间,或暴露只更新了一半的共享数据。安全设计必须说明哪些优先级可以抢占、何时重新置位 IF、每层使用多少栈空间,以及哪些数据需要临界区保护。
第 12.3 节说明了中断系统需要哪些策略。第 12.4 节将通过 8259 可编程中断控制器的具体寄存器和命令实现这些策略。