1. 中断系统到底在解决什么问题
1.1 从一个生活场景说起
你在家里写代码,突然快递小哥按门铃。你不可能每隔三十秒就跑去门口看一眼有没有人按铃——那样你什么都干不了。正常做法是:你继续写代码,门铃响了(这是一个信号),你暂停手头的工作,去开门签收,回来之后从刚才停下的地方接着写。这个“暂停—处理—恢复”的过程,就是中断。
计算机里的I/O设备跟CPU的关系一模一样。CPU跑主程序好比你在写代码,I/O设备完成一次数据传输好比快递到了。如果没有中断机制,CPU就得不断轮询I/O设备的状态——“你好了没?你好了没?”——这就是程序查询方式,效率极低,CPU大量时间浪费在等待上。中断方式的核心价值就在于:CPU不需要主动等待,设备准备好之后主动通知CPU。
408考试里,程序中断方式是一个必考的大题点,而中断系统本身又是理解程序中断方式的前置知识。很多同学直接去背“中断隐指令”“中断向量”“多重中断”这些结论,结果题目稍微变一下就不会了。根因在于没有把中断系统这条链路打通。这篇文章我就把中断系统从头到尾拆一遍,把每个环节为什么这么设计讲清楚。
1.2 中断系统在整个I/O控制方式中的位置
计算机组成原理中,I/O设备与主机之间传送信息有五种控制方式:程序查询方式、程序中断方式、DMA方式、通道方式、I/O处理机方式。这五种方式是一个逐步解放CPU的过程。
程序查询方式是CPU全程参与,CPU发出命令后不断读取设备状态寄存器,直到设备就绪才传送数据。这个过程中CPU不能做别的事,利用率极低。
程序中断方式是在程序查询基础上改进的:CPU发出I/O命令后继续执行其他程序,设备完成数据准备后通过中断信号通知CPU,CPU再暂停当前程序去处理数据传送。这里的关键变化是CPU在等待期间可以执行其他任务。
DMA方式则更进一步,数据传送本身不经过CPU,由DMA控制器直接在内存和I/O设备之间搬运数据,CPU只在传送开始和结束时介入。
理解这个演进脉络很重要,因为408的题目经常让你比较不同方式的优缺点,或者计算某种方式下CPU的利用率。如果你不清楚中断方式在整个体系中的定位,这些题就很难做对。
1.3 中断系统需要解决的核心问题
一个完整的中断系统需要回答以下几个问题:
- 谁来发中断:哪些设备或事件可以产生中断请求?
- 怎么发:中断请求信号通过什么线路送到CPU?
- CPU什么时候响应:CPU在执行什么阶段检查中断请求?
- 怎么找到处理程序:CPU怎么知道该跳转到哪个地址去执行中断服务程序?
- 怎么保护现场和恢复现场:中断处理完了怎么回到原来的程序继续执行?
- 多个中断同时来怎么办:优先级怎么定?能不能嵌套?
这六个问题就是中断系统的全部核心内容。下面我逐个拆解。
2. 中断请求的产生与传递机制
2.1 中断源的分类
中断源就是能产生中断请求的源头。按位置分,中断源分为两大类:
内部中断(也叫异常):来自CPU内部,比如除零错误、溢出、非法指令、缺页等。这类中断的特点是跟当前执行的指令直接相关,是同步的。
外部中断:来自CPU外部,比如I/O设备完成了一次数据传送、定时器到期、键盘按下等。外部中断又分为可屏蔽中断和不可屏蔽中断。
可屏蔽中断就是CPU可以通过设置中断允许触发器来屏蔽的中断,I/O设备的中断通常属于这一类。不可屏蔽中断是CPU不能屏蔽的,比如电源故障,这类中断一旦发生CPU必须立即响应。
408考试中经常考的一个点是:不可屏蔽中断的优先级高于可屏蔽中断。原因很简单,电源故障这种事你不能等CPU处理完手头的I/O再说。
2.2 中断请求触发器与中断屏蔽触发器
每个中断源通常配两个触发器:
中断请求触发器(INTR):设备准备好后将其置1,表示“我发出了中断请求”。CPU响应中断后,这个触发器被清除。
中断屏蔽触发器(MASK):用来控制该设备的中断请求是否被允许送到CPU。当MASK为1时,该设备的中断请求被屏蔽,不会传到CPU。
这两个触发器的组合逻辑是:只有当INTR=1且MASK=0时,该设备的中断请求才会被送到CPU的中断请求线上。这个逻辑关系在408的选择题里经常出现,有时候会给你一个电路图让你判断某个设备的中断能否被响应。
注意:中断屏蔽触发器是“每个设备一个”,而CPU内部还有一个全局的中断允许触发器(EINT)。只有EINT=1且该设备的MASK=0时,中断才能被响应。这两个层级的屏蔽关系不要搞混。
2.3 中断请求的传递方式
多个设备的中断请求怎么送到CPU?有两种方式:
链式查询方式:所有设备共用一条中断请求线,CPU响应后发出中断响应信号,这个信号沿着设备链逐个传递。每个设备收到响应信号后,如果自己有中断请求且未被屏蔽,就截获这个信号,不再往下传。这种方式结构简单,但优先级固定(离CPU越近优先级越高),且一个设备故障可能影响后面的设备。
独立请求方式:每个设备有独立的中断请求线,CPU内部有一个中断优先级排队器。这种方式响应快、优先级灵活,但需要的线数多。
408考试中,链式查询方式的优先级判断是一个高频考点。题目经常给你一个链式结构图,问某个设备能否发出中断请求、CPU会响应哪个设备。核心判断逻辑就是:离CPU最近的、有中断请求且未被屏蔽的设备优先获得响应。
3. CPU响应中断的完整过程
3.1 CPU在什么时间点检查中断
CPU并不是随时随地都在检查中断请求。它只在每条指令执行完毕之后才去检查有没有中断请求。这个设计的原因很直观:一条指令的执行是一个不可分割的原子操作,如果中途被打断,指令执行到一半的状态很难保存和恢复。
具体来说,CPU在每个指令周期的最后一个时钟周期(或者说是指令执行阶段的末尾)去采样中断请求线。如果有未被屏蔽的中断请求,且EINT=1,CPU就进入中断响应周期。
这里有一个408常考的细节:中断响应周期通常需要两个机器周期。第一个机器周期用来关中断(将EINT置0),第二个机器周期用来保存断点和形成中断服务程序的入口地址。
3.2 中断隐指令
“中断隐指令”这个概念是408的高频考点,也是很多同学容易搞混的地方。中断隐指令不是一条真正的指令,它没有操作码,是CPU在响应中断时自动执行的一系列操作。之所以叫“隐指令”,是因为它对程序员来说是透明的——你在程序里看不到它,但CPU确实做了这些事。
中断隐指令完成的操作包括:
- 关中断:将EINT置0,禁止新的中断请求被响应。这是为了保证中断响应过程中不被打断。
- 保存断点:将当前PC的值(下一条要执行的指令的地址)保存到栈中或特定地址。这样中断处理完后才能回到正确的位置继续执行。
- 形成中断服务程序的入口地址:根据中断类型号,从中断向量表中取出对应的中断服务程序入口地址,送入PC。
注意:中断隐指令保存的只是断点(PC值),并不保存通用寄存器的内容。通用寄存器的保存是由中断服务程序自己通过指令完成的。这个区分在408的简答题里经常考。
3.3 中断向量与中断向量表
CPU怎么知道该跳到哪个地址去执行中断服务程序?答案是通过中断向量。
中断向量就是中断服务程序的入口地址。所有中断向量集中存放在内存的一个固定区域,形成中断向量表。每个中断源对应一个中断类型号,CPU根据这个类型号去中断向量表中查表,取出对应的入口地址。
中断向量表通常位于内存的最低地址区域(比如0x0000开始),每个中断向量占4个字节(两个字节存段地址,两个字节存偏移地址,这是x86实模式的做法)。在408的考试中,有时候会简化成每个向量占2个字节或4个字节,具体看题目给出的条件。
这里有一个容易出错的点:中断向量表存放的是中断服务程序的入口地址,不是中断服务程序本身。中断服务程序本身存放在内存的其他位置。这个区分在选择题里经常出现。
3.4 中断响应的时间开销
从设备发出中断请求到CPU开始执行中断服务程序,中间有一系列时间开销:
- 设备发出中断请求到CPU采样到:取决于CPU什么时候执行到指令末尾
- CPU响应中断并完成中断隐指令:通常2个机器周期
- 从向量表取出入口地址:一次访存操作
这些时间在408的计算题里可能会用到。比如题目给你CPU主频、指令执行时间、中断处理时间,让你计算某种I/O方式下CPU的利用率,你就需要把这些开销都算进去。
4. 中断服务程序的设计与现场保护
4.1 中断服务程序的基本结构
一个典型的中断服务程序包含以下几个部分:
- 保护现场:将中断服务程序中会用到的寄存器压栈保存
- 中断服务:执行具体的中断处理逻辑(比如从I/O端口读取数据)
- 恢复现场:将之前保存的寄存器从栈中弹出恢复
- 开中断(如果支持多重中断)
- 中断返回:执行IRET指令,从栈中弹出断点送回PC
这个结构看起来简单,但每一步都有讲究。比如保护现场到底要保护哪些寄存器?原则是:中断服务程序中会修改的寄存器都需要保护。如果某个寄存器中断服务程序不会碰,那就不需要保护。但实际编程中为了简单,通常会保护所有通用寄存器。
4.2 保护现场与恢复现场的实现
保护现场通常用压栈操作实现。在x86汇编中,典型的保护现场代码是:
push ax push bx push cx push dx push si push di恢复现场则是逆序弹出:
pop di pop si pop dx pop cx pop bx pop ax这里有一个关键细节:压栈和弹栈的顺序必须相反。因为栈是后进先出的结构,最后压入的必须最先弹出。如果顺序搞错了,寄存器的值就会串位,程序行为完全错乱。
实操心得:在408的简答题中,如果让你写出保护现场和恢复现场的代码,一定要保证顺序相反。这是阅卷的得分点。
4.3 断点的保存与恢复
断点的保存是在中断隐指令阶段自动完成的,不需要程序员干预。具体来说,CPU会将当前PC的值压入栈中。当中断服务程序执行IRET指令时,CPU会自动从栈中弹出之前保存的PC值送回PC,从而回到被中断的程序继续执行。
这里有一个容易混淆的地方:断点保存的是“下一条指令的地址”还是“当前指令的地址”?答案是下一条指令的地址。因为CPU是在一条指令执行完毕后才检查中断的,此时PC已经指向了下一条指令。所以保存的是下一条指令的地址,中断返回后从下一条指令继续执行。
4.4 多重中断的处理
多重中断也叫中断嵌套,是指CPU在处理一个中断的过程中,又响应了另一个优先级更高的中断请求。
要实现多重中断,需要满足两个条件:
- 在中断服务程序中提前开中断(将EINT置1)
- 新来的中断请求优先级高于当前正在处理的中断
中断嵌套的过程可以用栈来理解:每响应一次中断,就有一层新的断点和现场被压入栈中。中断返回时逐层弹出,就像剥洋葱一样。
408考试中,多重中断的考点主要集中在:
- 中断屏蔽字的设置:通过设置每个设备的MASK触发器,可以控制哪些中断可以被嵌套
- 中断优先级的判断:多个中断同时到来时,CPU先响应哪个
- 中断嵌套的层数计算:给定一系列中断请求的时间和优先级,画出CPU执行轨迹
5. 中断优先级与中断屏蔽的配合
5.1 中断优先级的确定方式
中断优先级有两种确定方式:
硬件优先级:由中断源的物理位置决定。在链式查询方式中,离CPU越近的设备优先级越高。这种方式优先级固定,不灵活。
软件优先级:通过设置中断屏蔽字来动态调整优先级。每个设备有一个屏蔽字,决定了它能屏蔽哪些设备的中断。通过修改屏蔽字,可以改变中断处理的优先级顺序。
408考试中,软件优先级是一个重点。题目通常给你几个设备,让你写出每个设备的中断屏蔽字,然后分析某种中断请求序列下CPU的执行轨迹。
5.2 中断屏蔽字的设置方法
中断屏蔽字是一个二进制串,每一位对应一个中断源。某位为1表示屏蔽该中断源,为0表示不屏蔽。
设置中断屏蔽字的原则是:一个设备的中断服务程序中,应该屏蔽所有优先级比它低或相等的设备,但不屏蔽优先级比它高的设备。这样才能保证高优先级的中断可以嵌套低优先级的中断,而低优先级的中断不能打断高优先级的中断。
举个例子:假设有四个设备A、B、C、D,优先级从高到低为A>B>C>D。那么:
| 设备 | 屏蔽字(A B C D) | 说明 |
|---|---|---|
| A | 1 1 1 1 | 屏蔽所有,因为A优先级最高 |
| B | 0 1 1 1 | 不屏蔽A,屏蔽B、C、D |
| C | 0 0 1 1 | 不屏蔽A、B,屏蔽C、D |
| D | 0 0 0 1 | 不屏蔽A、B、C,只屏蔽D |
这个表格是408的经典考点,几乎每年都会以某种形式出现。关键是要理解:屏蔽字中为1的位对应的设备,其中断请求会被屏蔽。
5.3 中断处理次序的分析方法
给定中断请求序列和屏蔽字,怎么分析CPU的处理次序?方法是:
- 按时间顺序列出所有中断请求
- 对每个中断请求,检查当前正在处理的中断的屏蔽字是否屏蔽了它
- 如果不被屏蔽且优先级更高,则嵌套执行
- 如果被屏蔽,则等待当前中断处理完毕后再响应
这个过程用画图的方式最清晰。横轴是时间,纵轴是程序执行流,每个中断画成一个矩形块,嵌套关系用缩进表示。
实操心得:做这类题的时候,一定要先确认每个设备的屏蔽字,然后严格按照时间顺序逐个判断。不要凭感觉跳步,否则很容易出错。
6. 程序中断方式下的数据传送全流程
6.1 从CPU发出I/O命令到数据传送完成
把前面所有知识串起来,程序中断方式下一次完整的数据传送流程是这样的:
- CPU执行I/O指令,向设备发出读/写命令,同时将设备的中断允许触发器置位
- CPU继续执行后续指令(不等待设备)
- 设备收到命令后开始工作,准备数据
- 设备准备好数据后,将中断请求触发器置1,向CPU发出中断请求
- CPU在每条指令执行完毕后检查中断请求线
- CPU发现有效中断请求且EINT=1,进入中断响应周期
- 执行中断隐指令:关中断、保存断点、取中断向量
- 跳转到中断服务程序,保护现场
- 执行数据传送(从设备读取数据到内存或寄存器)
- 恢复现场,开中断,执行IRET返回
- CPU回到被中断的程序继续执行
这个流程在408的答题中经常需要完整写出。关键是要把每一步的先后顺序和依赖关系搞清楚。
6.2 中断方式与查询方式的对比
| 对比项 | 程序查询方式 | 程序中断方式 |
|---|---|---|
| CPU等待 | 全程等待,不能做其他事 | 等待期间可执行其他程序 |
| 数据传送 | CPU主动读取 | 中断服务程序中传送 |
| 硬件开销 | 小 | 需要中断控制器等 |
| CPU利用率 | 低 | 高 |
| 适用场景 | 简单设备、低速设备 | 大多数I/O设备 |
这个对比表在408的简答题里经常出现。核心区别就是CPU在等待期间能不能做别的事。
6.3 中断方式下CPU利用率的计算
这是408计算题的高频考点。基本思路是:
- 假设CPU主频为f,每条指令平均执行时间为T
- 设备传送一次数据需要的时间为T_io
- 中断处理(包括隐指令、保护现场、传送数据、恢复现场)需要的时间为T_int
- 则在程序中断方式下,CPU用于I/O的时间占比为T_int / T_io
具体计算时要注意单位统一,以及是否考虑中断响应延迟等因素。题目通常会给出足够的信息,关键是把每个时间分量都找全。
7. 408真题中的典型考法与避坑指南
7.1 中断隐指令相关真题分析
24年45题考的就是中断隐指令的相关内容。这类题目的典型问法是:“中断隐指令完成的操作有哪些?”或者“中断隐指令由谁执行?”
核心要点:
- 中断隐指令由硬件自动执行,不是程序员编写的指令
- 完成的操作:关中断、保存断点、取中断向量
- 不保存通用寄存器的值(这是中断服务程序的事)
很多同学容易把“保存断点”和“保护现场”搞混。断点是PC值,由硬件在中断隐指令中保存;现场是通用寄存器的值,由软件在中断服务程序中保存。这个区分一定要记牢。
7.2 中断屏蔽字与优先级真题分析
这类题目通常给你一个中断请求序列和每个设备的屏蔽字,让你画出CPU的执行轨迹。解题步骤:
- 列出所有中断请求及其到达时间
- 确定每个设备的屏蔽字
- 从第一个中断请求开始,逐个判断是否能嵌套
- 画出时间轴上的执行轨迹
常见的坑:
- 忘记检查EINT的状态(中断服务程序中是否开了中断)
- 屏蔽字的位序搞反(是从左到右还是从右到左对应设备)
- 忽略了同级中断不能嵌套的规则
7.3 常见问题速查表
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 中断隐指令和保护现场混淆 | 概念不清 | 记住:隐指令保存断点(PC),软件保存现场(寄存器) |
| 屏蔽字位序搞反 | 没有确认题目约定 | 仔细读题,确认位序方向 |
| 多重中断嵌套判断错误 | 忘记检查EINT | 中断服务程序中只有开中断后才能嵌套 |
| 中断向量和中断服务程序混淆 | 概念不清 | 向量是入口地址,服务程序是代码本身 |
| 优先级判断错误 | 混淆硬件优先级和软件优先级 | 有屏蔽字时以屏蔽字为准 |
7.4 独家避坑技巧
技巧一:做中断嵌套题时,先画一条时间轴,把每个中断请求标在轴上,然后从第一个开始逐个分析。不要试图在脑子里同时跟踪多个中断,容易乱。
技巧二:判断一个中断能否嵌套时,问自己三个问题:当前EINT是否为1?新中断是否被当前屏蔽字屏蔽?新中断优先级是否更高?三个条件都满足才能嵌套。
技巧三:写中断服务程序的伪代码时,严格按照“保护现场—开中断—中断服务—关中断—恢复现场—中断返回”的顺序。开中断的位置很关键,放在保护现场之后、中断服务之前,这样才能实现多重中断。
技巧四:计算CPU利用率时,先列出所有时间分量,再代入公式。不要跳步,408的计算题往往就是考你细心。
8. 从唐朔飞教材到408真题的衔接
8.1 唐朔飞教材中中断系统的重点章节
唐朔飞《计算机组成原理》中,中断系统主要分布在I/O系统这一章。重点内容包括:
- 中断的基本概念和中断源的分类
- 中断请求触发器与中断屏蔽触发器
- 中断判优逻辑(链式查询和独立请求)
- 中断隐指令
- 中断向量和中断向量表
- 多重中断和中断屏蔽字
课后题中,中断屏蔽字的设置和多重中断的执行轨迹分析是必做题。建议把课后题全部做一遍,尤其是画执行轨迹的题。
8.2 王道教材的补充重点
王道《计算机组成原理》在中断系统部分补充了一些408真题的解析,特别是:
- 中断响应周期的时序分析
- 中断方式下CPU利用率的计算
- 中断嵌套的详细过程
王道书上的题量更大,适合用来刷题巩固。但要注意,王道书上的某些简化处理可能和唐朔飞教材有细微差异,以408真题的答案为准。
8.3 从知识点到做题的转化方法
很多同学知识点背得很熟,但一做题就卡壳。问题出在没有把知识点转化成解题步骤。我的建议是:
对于中断屏蔽字题,固定解题流程:读题确认设备数和优先级→写出每个设备的屏蔽字→按时间顺序分析中断请求→画执行轨迹。
对于中断隐指令题,固定答题模板:先答“由硬件自动执行”,再逐条列出完成的操作,最后补充“不保存通用寄存器”。
对于CPU利用率题,固定计算步骤:列出所有时间分量→确认单位→代入公式→检查结果是否合理。
这种“固定流程”的方法看起来机械,但在考场上能帮你节省大量思考时间,减少出错概率。
8.4 实验环节的补充理解
如果有条件做计算机组成原理实验,建议重点做中断相关的实验。在实验箱上,你可以实际观察中断请求信号的产生、CPU响应中断的过程、中断服务程序的执行和返回。这种直观的观察比看书本上的时序图要深刻得多。
实验中最容易观察到的一个现象是:中断响应的时机确实是在指令执行完毕之后。你可以通过单步执行的方式,观察CPU在每条指令结束时才去采样中断请求线。这个现象在书本上只是一句话,但亲眼看到之后理解会完全不一样。
中断系统这块内容,说到底就是一条链路:设备发请求→CPU在指令末尾检查→响应后关中断保存断点→查向量表跳转→保护现场→处理→恢复现场→返回。把这条链路打通,408里跟中断相关的题目基本都能拿下。我在复习的时候是把这条链路默写了十几遍,直到能闭着眼睛画出来。后面做真题的时候,不管题目怎么变,核心逻辑都是这一套。