第18章 中断和异常的处理与抢占式多任务

本章学习内容:
中断和异常中断的工作机制
中断和异常中断的分类
IDT,中断门和陷阱门
采用硬件中断实施抢占式任务切换的原理和过程
lidt, bound, nop, ud2

1.中断和异常

1.1 中断

中断分为硬件中断和软中断
硬件中断是由外围硬件设备发出的中断信号引起的
软中断是由int n指令引发的中断处理

1.2 异常

异常是处理器内部产生的中断,表示在指令执行的过程中遇到了错误的状况。
异常分为三种,指令执行异常,程序调试异常和机器检查异常。
指令异常是执行指令的过程中检测到了程序的错误
程序调试异常是为程序调试而特地提供的指令,由into, int3, bound引发
机器检查异常是检测和报告跟硬件有关的错误
根据性质和严重程度,异常又分为3类,故障、陷阱和中止
故障通常是可以纠正的
陷阱是陷阱条件成立时才产生中断
终止是最严重的错误,比如硬件错误等

1.3 中断描述符表

IDT,interrupt descriptor table,中断描述符表。这个表中保存中和中断处理有关的描述符,包括中断门、陷阱门和任务门
整个系统只有一个IDT,IDT的位置信息记录在IDTR中
IDTR包含6个字节,分别是4个字节的偏移地址和2个字节的界限值,因此IDT最大可以是64k
X86系统最多支持256个中断,所以IDT的最大为2kB
在保护模式下,前20个中断向量基本上都是留给内部异常的。
为了使系统支持中断,需要中断处理过程、中断门、中断描述符表
本章的代码清单在core程序的公共例程段提供了一个过程general_interrupt_handler用于处理内部异常,这个就是中断处理过程
需要定义一个中断门指向这个公共例程
然后把这个中断门安装到IDT中。
异常发生时,处理器会根据中断向量,即中断号从IDT中获取一个中断门,从中断门中获取到一个选择子,根据这个选择子选择从LDT或者GDT中获取一个段描述符,从而知道了中断处理过程的基地址,再加上中断门中的偏移地址,就可以得到中断处理过程的线性地址。

1.4 中断门/陷阱门

(1)调用门、任务门、中断门、陷阱门对比
(2)调用门里包含一个选择子和一个偏移地址
(3)任务门里是一个TSS的选择子
(4)中断门里是一个段选择子和偏移地址
(5)陷阱门里也是段选择子和偏移地址,陷阱门和中断门只有1bit的差异
(6)中断门和陷阱门只能保存在IDT中

2.内核的加载和初始化

2.1 内核加载和初始化过程

程序进入到内核程序开始执行后,处理器已经进入保护模式了,准备创建内核任务和用户任务并执行任务切换,内核任务创建的过程如下:
初始化中断系统
(1)在公共例程段定义一个通用异常处理程序general_exception_handler,为这个程序构建段描述符并存放到GDT中,这样就得到了这个段的描述符的选择子
(2)为这个程序安装中断门。中断门中需要这个处理程序的描述符的段选择子和偏移地址。
(3)将通用异常处理对应的中断门安装到IDT的前20个表项中
(4)在公共例程段定义一个通用中断处理程序general_interrupt_handler,,为这个程序构建段描述符并存放到GDT中,这样就得到了这个段的描述符的选择子
(5)为这个程序安装中断门。
(6)将通用中断处理对应的中断门安装到IDT的后236个表项中

为0x70号中断安装中断门
(1)定义一个实时时钟中断的中断处理程序rtm_0x70_interrupt_handle
(2)构建一个这个中断处理程序的描述符并安装到GDT中
(3)构建一个这个描述符的中断门并安装到IDT中
加载中断描述附表寄存器IDTR
初始化8259a芯片
初始化RTC芯片
创建内核任务并执行
创建用户任务并执行
开放硬件中断,即执行sti指令
此时,等待RTC的更新周期结束中断,如果中断发生,则进入中断处理程序执行

(1)首先向8259a发送EOI命令。EOI是中断结束命令
(2)读一下CMOS寄存器C,使它复位一下
(3)执行任务调度。调用initiate_task_switch来执行
(4)确定下一个应该被执行的任务,并切换到那个任务
控制流转移
在中断处理程序中执行了任务切换,切换以后进入到新任务执行
再次发生中断时,又在中断处理函数中发生任务切换,又回到旧任务
旧任务的TSS保存的CS和EIP指向的是中断处理函数里的指令,因此继续执行中断处理函数,直到执行到iretd。
此时回到旧任务自己的程序中

2.2 知识点

关于8259a芯片

8259a芯片由2个芯片级联组成
主片和从片的默认中断向量分别是0x080x0f和0x700x77
32位处理器上前20个中断向量被用作处理器异常向量
因此在使用8259a前需要重配主片的中断向量
8259a的主片和从片各有2个端口,端口号分别为x020、0x21和0xa0、0xa1
在对8259a进行初始化的时候需要用到ICW1~ICW4指令

中断和异常处理程序的保护

利用中断和异常进行控制转移的时候也会进行特权级检查
发生中断的时候,处理器首先会根据中断向量找到中断门,再根据中断门找到中断处理程序,即目标代码段
要成功的执行中断处理程序,需要满足以下条件
当前特权级CPL等于或者低于目标代码段DPL
当执行的是软中断int n,单步中断int3,以及into引发的中断时,需要满足CPL必须大于或者等于中断门的DPL
当执行的是其他中断时,不对中断门的DPL进行检查
当特权级检查没通过的时候会引发常规保护异常

中断任务

当中断或异常发生的时候,从IDT中找到的门是任务门,则执行任务切换,这是硬件任务切换。

错误代码

有些异常产生时,处理器会在异常处理程或者中断任务的栈中压入一个错误代码
通常这意味着异常和特定的段选择子或者中断向量有关

关于RTC

计算机主板上有实时时钟芯片RTC。
RTC可以定时产生更新周期结束中断信号
RTC的中断线和8959a从片的第一个引脚相连,8259a从片第一个引脚的中断向量是0x70。

3.指令

bound

用于检查数组的索引是否在边界之内
bound r16, m16
r16是寄存器,m16是内存
M16指向的内存中保存着数组的上界限和下界限的值,r16中保存着要检查的索引
Bound会查看存储在r16中的索引值是否低于数组的下界限,或者大于数据的上界限

ud2

引发一个异常
无操作数

iretd

中断返回
默认操作尺寸为16位时,按照操作尺寸32位出栈
默认操作尺寸为32位时,按照操作尺寸32位出栈
16位出栈是指每次从栈中弹出一个字
32位出栈是指每次从栈中弹出一个双字

iret

中断返回
默认操作尺寸为16位时,按照操作尺寸16位出栈
默认操作尺寸为32位时,按照操作尺寸32位出栈

lidt

加载中断描述符表寄存器
lidt m
m是内存地址,在此地址处有6字节的数据,其中前4个字节是中断描述符表的线性基地址,后2个字节是中断描述符表的大小

lldt

加载局部描述符表寄存器
lldt m
m是内存地址,在此地址处有6字节的数据,其中前4个字节是局部描述符表的线性基地址,后2个字节是局部描述符表的大小

lgdt

加载全局描述符表寄存器

lidt m

m是内存地址,在此地址处有6字节的数据,其中前4个字节是全局描述符表的线性基地址,后2个字节是全局描述符表的大小

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值