异常和中断响应过程

前两节说清了”有哪些事件”和”事件属于哪一类”。这一节说从请求到返回,完整发生了什么。

教材在这里写得比较薄,但这一节实际上有三块独立的、都能出大题的内容:

  1. 中断隐指令——硬件那三件事,以及为什么必须是这三件、必须是这个顺序
  2. 判优(仲裁)——多个请求同时到达时选谁,三种电路各有各的代价
  3. 屏蔽字与嵌套——谁能打断谁,以及这件事为什么可以用软件改

第 2、3 块教材归在第 7 章 I/O 的程序中断方式里讲(7.3.2),但它们的原理属于本节,分开记会两边都记不牢。本节按完整机制写,第 7 章只补 I/O 特有的部分。

机制

一、响应的四个条件

响应设备提出请求该设备未被屏蔽开中断一条指令刚执行完指令边界

四个条件缺一不可。 判断”某中断能否被响应”的题目,逐项核对即可。

注意 NMI 不受第二、三项限制(5.5.2),而异常不受第四项限制——异常在指令执行过程中就被发现,不必等指令结束。

二、中断隐指令:硬件的三件事

“隐”的意思是它没有操作码、不在主存里、程序里找不到它。 它是 CPU 自己的一段硬件动作。

顺序动作为什么必须漏了会怎样
1关中断(IF ← 0)保护接下来的保存动作不被打断保存断点的过程中又来一个中断,第一个断点会被覆盖
2保存断点(PC、PSW 入栈或存专用单元)将来要回来回不去
3引出中断服务程序(入口地址 → PC)转过去执行不知道去哪

顺序不能换,而且”关中断在第一位”是有硬理由的。

保存断点需要若干个时钟周期(要访存)。如果在这期间响应了第二个中断,第二次隐指令又会去保存断点——而此时 PC 已经被第一次改成服务程序入口了,于是存下去的是错的,第一个程序永远回不来。关中断把这段窗口保护了起来。

这就是”临界区”这个概念在硬件上最早的形态——一段不能被打断的操作,靠”暂时关掉打断源”来保护。跨到 OS,临界区用的锁、以及内核里的关中断保护,是同一个思路的软件版本。

顺带解决一个高频疑问:既然关了中断,嵌套怎么发生? ——靠中断服务程序里主动开中断。硬件只保证”保存断点这段”不被打断,开中断的时机交给软件决定,见下面第四块。

三、中断向量:三个名字,别混

这三个词长得像,指的是三个不同层次的东西。

名字是什么类比
中断类型号一个小整数,标识是哪个中断源数组下标
中断向量地址该中断向量在向量表中的地址数组元素的地址
中断向量中断服务程序的入口地址数组元素的值

三步链条:

中断类型号表项大小表基址中断向量地址访存查表中断向量(入口地址)

这个”用小整数查一张入口地址表”的模式,本章和上一章一共出现三次,形状完全相同:

出处索引用的整数表查出来的入口
4.3.2 switchcase 的值跳转表分支代码的入口
5.4.3 测试操作码控制存储器该指令微程序的入口
本节中断类型号中断向量表中断服务程序的入口

三处都是”编号 → 入口地址”的一次映射,都靠一张预先建好的表,都省掉了一长串比较判断。 认出这个模式,三处的题目就是同一道题的三种外衣。

两种识别中断源的方式:

方式怎么找到入口特点
向量中断硬件给出类型号,查向量表直接得入口快,主流
查询中断转入一段公共服务程序,软件逐个查设备状态位慢,但硬件简单

“判断中断源”这一步归硬件还是软件,取决于用哪种方式——5.5.2 那张分工表里这一行之所以写着”两者皆可”,原因就在这里。

四、中断判优:三种仲裁方式

多个中断源同时提出请求时,选哪一个? 这就是判优(仲裁)。三种做法,代价各不相同。

(1)软件查询法

转入一段公共程序,按预定顺序逐个测试各设备的中断请求触发器,第一个测到的就是优先级最高的。

if (设备1请求) goto 服务1;
if (设备2请求) goto 服务2;
...
优先级由什么定查询的先后顺序——写在程序里
改优先级改程序即可,最灵活
硬件几乎不需要
速度最慢——设备多时要测很多次

(2)链式查询(菊花链,Daisy Chain)

所有设备串在一根”中断响应”信号线上,CPU 发出的响应信号从链头依次往下传。

设备设备设备

规则:某设备若正在请求,就”吃掉”这个响应信号,不再往下传;若没请求,就原样传给下一个。

优先级由什么定物理位置——离 CPU 越近优先级越高
改优先级要重新接线,最不灵活
硬件最省——只要一根链式信号线
速度中等,信号要逐级传递
可靠性差——链上任一设备的传递电路坏了,它后面全部失效

(3)独立请求方式(并行判优)

每个设备有自己独立的请求线和响应线,全部接到一个优先权编码器上,由硬件电路一次性选出优先级最高的。

优先级由什么定编码器的逻辑——可做成可编程的
改优先级若编码器可编程则可以改
硬件最费—— 个设备要 根线
速度最快——一级组合逻辑出结果

三者对比

软件查询链式查询独立请求
速度最慢中最快
硬件成本最低低最高
线数——1 根链 根
优先级改变最容易(改程序)最难(改接线)中(可编程编码器)
优先级取决于查询顺序物理位置编码器逻辑

三者是一条”用硬件换速度”的连续谱,两端分别是”全软件、最慢最省”和”全硬件、最快最贵”。

关联对照:中断判优 / 总线仲裁

两套三方式是同构的——都在解决”多个请求者争一个资源,选哪个”:

中断判优总线仲裁(6.2.1)
链式查询(菊花链)链式查询(同名同构)
独立请求独立请求(同名同构)
软件查询计数器定时查询

前两种连名字都一样,判据也一样:链式查询靠物理位置定优先级、省线但不灵活;独立请求靠编码器、快但费线。

认出同构之后,两章只需记一套。 第 6 章那一套多出的”计数器定时查询”是链式与独立请求的折中——用计数器广播设备号,命中的设备应答。

五、响应优先级与处理优先级

这是本节最容易失分的一处辨析,也是”中断屏蔽字”存在的全部理由。

响应优先级处理优先级
决定什么同时到达时先响应谁嵌套时谁能打断谁
由什么决定判优电路(上面三种之一)中断屏蔽字
能否用软件改变不能能

两者可以不一致,而且题目故意让它们不一致。

例:设备 A 的响应优先级高于 B。若把 B 的屏蔽字设成”不屏蔽 A”,而把 A 的屏蔽字设成”屏蔽 B”,那么:

  • 同时请求时,先响应 A(响应优先级)
  • B 正在服务时 A 来了,A 能打断 B(B 没屏蔽 A)
  • A 正在服务时 B 来了,B 打不断 A(A 屏蔽了 B)

此时处理优先级 A > B,与响应优先级一致。 但只要把屏蔽字反过来设,就能做出”响应优先级 A>B 而处理优先级 B>A”的效果。

这就是为什么屏蔽字是软件可写的:判优电路是焊死的,但**“谁能打断谁”这件事和具体应用有关**,必须留给软件调整。

六、中断屏蔽字与嵌套

每个中断源配一个屏蔽字,进入它的服务程序时把这个屏蔽字送入屏蔽寄存器。屏蔽字中某位为 1 表示屏蔽对应的中断源。

屏蔽字表的读法(考试原样出现):

中断源屏蔽 1屏蔽 2屏蔽 3屏蔽 4
11111
20111
30011
40001

三条读法规则:

  1. 对角线一定是 1——每个中断源都屏蔽自己,否则它的服务程序会被自己无限嵌套
  2. 某行 1 越多,这个中断源的处理优先级越高——它能屏蔽掉的别人越多
  3. 上表是”处理优先级 1>2>3>4”的标准形态;题目若给非三角形的屏蔽字表,就说明处理优先级被人为调整过

多重中断(嵌套)成立的两个条件:

  1. 中断服务程序中要有”开中断”指令——而且要放在保存现场之后
  2. 高优先级的中断源没有被当前屏蔽字屏蔽

第 1 条决定了服务程序的标准骨架:

中断服务程序:
    保存现场(通用寄存器入栈)      ← 此时仍是关中断
    设置本中断源的屏蔽字
    开中断                        ← 从这里开始允许嵌套
    ...具体处理...
    关中断                        ← 保护恢复现场
    恢复屏蔽字
    恢复现场
    开中断
    IRET                          ← 恢复 PC 和 PSW

“保存现场时必须关中断、处理时可以开中断”——这个骨架和中断隐指令里”关中断放第一位”是同一个道理的延续:凡是会破坏”回得去”这个性质的操作,都必须在关中断状态下做。

单重中断就是把中间那条”开中断”去掉:服务程序全程关中断,任何新请求都要等它结束。

七、完整时序

flowchart TB
    A["指令执行完毕"] --> B{"有请求且允许?"}
    B -->|否| A
    B -->|是| C["判优:选出优先级最高的中断源"]
    C --> D["中断隐指令(硬件)<br/>①关中断 ②保存断点 PC/PSW ③入口地址→PC"]
    D --> E["保存现场(软件,关中断状态下)"]
    E --> F["设置屏蔽字 + 开中断"]
    F --> G["具体处理"]
    G --> H["关中断 + 恢复屏蔽字 + 恢复现场"]
    H --> I["开中断 + IRET"]
    I --> A

    classDef hw fill:#fecaca,stroke:#dc2626,stroke-width:2px
    classDef sw fill:#dbeafe,stroke:#2563eb,stroke-width:2px
    classDef judge fill:#f3f4f6,stroke:#6b7280
    class C,D hw
    class E,F,G,H,I sw
    class B judge

红色是硬件,蓝色是软件,分界线正好在”保存断点”与”保存现场”之间(5.5.2)。

八、精确异常与流水线

上面所有讨论都默认”指令是一条一条执行完的”。流水线里这个前提不成立——异常发生时,流水线里同时有五条指令处于不同阶段。

精确异常(precise exception)的要求:

异常发生时,它之前的所有指令必须已经全部完成,它之后的所有指令必须一条都没有生效,就好像程序是严格顺序执行到那一点的。

实现手段:让流水线里该指令之后的所有指令作废(flush),之前的指令继续走完,然后再响应异常。

为什么必须精确:不精确的话,操作系统拿到的现场是”一半新一半旧”的,缺页之后根本无法正确重启那条指令(5.5.2 说故障要重执行当前指令)。虚拟存储器能工作,前提就是精确异常。

这也是 5.5.1 那条”指令边界响应保证了 ISA 抽象”在流水线上的延续——流水线破坏了物理上的指令边界,精确异常把逻辑上的指令边界重新造了出来。 详见 5.6.3。

边界

边界辨析:响应优先级 / 处理优先级

  • 响应优先级:判优电路决定,软件不能改,管”同时来了先响应谁”
  • 处理优先级:中断屏蔽字决定,软件可以改,管”嵌套时谁能打断谁”

二者可以不一致。这是本节最高频的辨析题。

边界辨析:中断向量 / 中断向量地址 / 中断类型号

  • 中断类型号:小整数,标识中断源
  • 中断向量地址:向量在表中的地址
  • 中断向量:服务程序的入口地址(表项的值)

“中断向量 = 入口地址”这一条最常被记反成”中断向量 = 向量表的地址”。

边界辨析:关中断在隐指令中的位置

必须在保存断点之前。 否则保存断点这几个周期内若再来中断,第一个断点会被覆盖,程序永久回不去。

同理,恢复现场之前也要关中断。判据统一:凡是会破坏”回得去”的操作,都要在关中断状态下做。

层次辨析:三种判优方式

  • 软件查询:靠查询顺序,最灵活最慢,几乎不用硬件
  • 链式查询:靠物理位置,最省线,改优先级要重新接线,链上一环坏则后面全瞎
  • 独立请求:靠优先权编码器,最快最费线( 根)

与总线仲裁的三方式同构,见 6.2.1。

边界辨析:单重中断 / 多重中断

差别只在服务程序里有没有”开中断”这条指令,以及位置在哪。

  • 没有 → 单重,全程不被打断
  • 有,且在保存现场之后 → 多重(嵌套)

开中断绝不能放在保存现场之前——那样嵌套会破坏还没存完的现场。

对照速查

动作谁做什么时候
关中断硬件隐指令第 1 步
保存断点(PC、PSW)硬件隐指令第 2 步
送服务程序入口硬件隐指令第 3 步
保存现场(通用寄存器)软件服务程序开头,关中断状态下
设置屏蔽字软件保存现场之后
开中断软件允许嵌套的起点
恢复现场软件关中断状态下
恢复 PC、PSW硬件(IRET 触发)最后
判优方式优先级取决于速度线数
软件查询查询顺序慢——
链式查询物理位置中1 根链
独立请求编码器逻辑快
屏蔽字表读法含义
对角线为 1每个中断源屏蔽自己
某行 1 的个数多该中断源处理优先级高
标准下三角形态处理优先级 = 编号顺序
非三角形态处理优先级被人为调整过

考点

  • 中断隐指令三件事 + 顺序:关中断、保存断点、送入口。关中断必须在最前,要能说出理由。
  • 给屏蔽字表求 CPU 运行轨迹:本节最大的大题。画时间轴,逐个事件判断”当前屏蔽字允不允许”。
  • 响应优先级 vs 处理优先级:判断某题改的是哪一个。改屏蔽字只能改处理优先级。
  • 三种判优方式的对比:速度、线数、优先级如何决定、能否修改。
  • 多重中断的两个条件:服务程序中开中断 + 未被屏蔽。
  • 中断向量三个词的辨析:向量 = 入口地址。
  • 精确异常:答异常之前的指令全部完成,之后的指令全部作废;它是虚拟存储器能工作的前提。

链接