x86处理器中断与异常浅析
中断与异常的概念
- 详细的理论部分可以参考之前的笔记中断与异常理论
名词解释
- 中断: 由硬件引发的, 通常分为可屏蔽中断和不可屏蔽中断
- 异常
- 由指令执行引发的, 比如除零异常
- 80*86处理器大约有20多种异常的处理
- 对于某些异常, 程序会在处理前产生硬件出错码,并压入内核态堆栈
- 系统调用: 异常的一种, 用户态到核心态的唯一入口
- 中断控制器(PIC或APIC): 负责将硬件的中断信号转化为中断向量,并引发CPU中断
实模式
- 中断向量表: 存放中断程序的入口地址
- 入口地址=段地址左移4位+偏移地址
- 不支持CPU运行状态切换
- 因为没有CPU状态的切换, 中断处理和一般过程调用很相似
保护模式
- 在保护模式中, 中断向量表又叫做中断描述符表
- 中断向量在该模式中又称作门(gate), 其中gate表示一种数据结构
x86处理器对中断的支持
四种门描述符
- 任务门
- 中断门
- 给出了段选择符, 中断/异常程序的段内偏移量(通过这两个是可以确定中断程序的入口地址的)
- 通过中断门后, 系统会自动禁止新中断
- 陷阱门
- 流程和中断门相似
- 通过陷阱门之后, 系统还可以接受新的中断(和中断门的区别)
- 调用门
总体流程
- 先来一张流程图, 这里直接借用陈老师讲课的图了, 非常清晰(主要是我自己画不出这个感觉),转自这里
- 中断/异常的硬件处理过程
- 确定与中断或异常关联的向量i
- 通过IDTR寄存器找到IDT表, 获取中断描述符表中的中断描述符(表中第i个)
- 中断描述符中找到段选择符, 这个段选择符中存在对GDT表的索引
- 通过GDTR寄存器找到GDT表的地址,结合段选择符中的索引,找到段描述符,上图中有段描述符的格式
- 之后我们将段基址和中断描述符中的偏移量经过处理就得到我们中断程序入口地址了
- 中途要做很多特权级检查:
- 当特权优先级发生变化时,响应的堆栈也要切换(例如用户态->核心态),那么相应的堆栈也要切换成核心态的
- 硬件压栈,保存上下文环境; 异常产生了则将错误码压入栈.
- 如果是中断门, 清除IF位,陷阱门则无需做这件事
- 将上面得到的中断描述符中的偏移量和段描述符中的基地址我们可以计算出中断程序的入口地址,从而执行第一条指令
参考
[1] 操作系统原理