12.1 为什么需要中断与异常
第 11 章让软件反复读取状态端口,直到设备就绪。这种查询(polling)循环容易理解,但即使设备状态没有变化,CPU 仍在不断询问“准备好了吗”。中断(interrupt)是一种事件请求:CPU 暂时离开当前程序,运行处理该事件的程序,随后回到原来的工作。
用事件驱动服务替代反复检查
假设键盘每隔几千条指令才产生一个字节。紧密查询循环可以迅速发现按键,但绝大多数端口读取只会得到“未就绪”;降低查询频率能够节省 CPU 时间,却会增加按键得到处理前的延迟。
使用中断驱动 I/O 时,CPU 可以继续执行有用的前台工作。接口有数据后发出中断请求。处理器完成当前指令,保存足以返回的状态,转去执行中断服务程序(interrupt service routine, ISR),处理设备,再恢复状态并继续原程序。
中断消除了反复检查,却不会让服务变成零成本。进入中断、保存状态、执行服务程序和返回都要消耗时间。事件过于频繁时,中断开销反而可能占据主要部分。因此,设计问题不是“中断永远比查询好”,而是哪种方法能在给定事件频率下同时满足响应延迟和 CPU 占用要求。
按控制转移的来源分类
外形相似的控制转移并不都有相同来源和时序:
- 硬件中断(hardware interrupt)来自 CPU 外部。8086 的
INTR是可屏蔽请求,NMI是为紧急事件保留的不可屏蔽请求。
- 软件中断(software interrupt)由
INT 21H等指令主动请求。
- 异常(exception)由 CPU 因当前指令产生,例如除法错误。
外部设备事件通常是异步(asynchronous)的:它不是当前指令造成的,CPU 会在规定的指令边界接收它。除法错误则是同步(synchronous)的:使用相同操作数再次执行同一指令,事件会在相同位置重现。
8086 的中断允许标志 IF 控制可屏蔽 INTR 的接收。清除 IF 会推迟 INTR,却不能阻止 NMI、软件 INT 或处理器检测到的异常。软件进入临界步骤并认为“已经关闭全部中断”时,必须理解这一区别。
第 12.1 节说明了控制为何离开前台程序,以及哪些事件能够引发这种转移。第 12.2 节将寻找服务程序的准确地址,并追踪被保存的机器状态。