1,x86中断系统
所谓中断,就是使CPU更改当前指令流程的信号。
中断分为同步中断和异步中断,前者也称为异常,后者则是我们常说的中断。后者有可分为三种外部I/O中断,处理器之间的中断,和??。中断又可分为可屏蔽中断和不可屏蔽中断。不可屏蔽中断大多是系统硬件错误,系统不能不处理的事件。
---------------------------------------------------------------------------------------------------------------------------------
80x86有两条中断请求线:非屏蔽中断NMI线和可屏蔽中断INTR线,当这两条线上收到中断请求信号而引起中断时,称这类中断为硬中断.(NMI线直接接CPU引脚,INTR线接8259A中断控制器)
非屏蔽中断和屏蔽中断
非屏蔽中断
当NMI线上出现一个由低上跳的高电平中断请求信号后(持续时间须大于两个时钟周期),不管标志位I状态如何,当前指令执行完后,X86CPU马上转入中断处理. 此类型中断有来源;系统板上RAM产生奇偶错,协处理器上来的中断请求,I/O通道检查出错,intel保留的中断0x00~0x1F,软中断.
可屏蔽中断
当INTR线上出现一个高电平中断请求信号后(必须保持到当前执行的指令结束为止),CPU是否响应该中断,取决于标志信I的状态,若I=0,则不响应.(INTR线接8259A中断控制器)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
如何进入中断?
中断服务例程实际上就是一段代码,进入中断的目的就是执行这一段代码。不同的硬件架构有不同的实现方式。较简单的方式如8086,ARM,在RAM开始部分的固定位置,默认被初始化为中断向量表,一般从0开始,大小为4 Byte*中断数。中断向量表中的每一项即为一个中断的入口。当有中断发生时,系统跳转到中断向量表中这个中断的入口地址开始执行。
在x86架构中,实现较为复杂。由于使用保护模式和段式管理,在x86中进入中断是通过们来实现的(系统调用,异常,所以从用户态到内核态的切换都通过门来实现)。
在x86架构,同样也存在中断向量表,与8086不同的是,这个向量表的起始地址不再是0,而是由idtr寄存器来指定,这也就意味着中断向量表可以放到内存的任何地方;第二个不同的是,中断向量表中存放的不是终端服务例程,而是各种门。
在x86中,定义了4种们,任务门,中断们,陷门,调用门,分别对应了四种从低优先级态到高优先级态的切换方式。中断使用的是中断门。每个门的大小是64bit,中断门中有一个16位的段选择符和段内偏移。
当中断发生时,CPU通过读取中断控制器得到中断号,然后进入对应的门,通过中断门中的段选择符,在GDT或LDT中找到对应的代码段,加上段内偏移,即可找到中断服务例程。
当然进入中断过程并不是像上面说的这么简单,跟其它门的进入方式相同,进入中断服务例程前要检查权限,保存上下文和切换堆栈。
检查权限:门是有权限限制,当试图进入门的CPL小于门得DPL时,某些门是不允许进入的,当然中断门对中断没有这个限制。
保存上下文是为了从中断服务例程中返回时,可以回到被中断的指令流继续执行。上下文包括通用寄存器,堆栈等。这些信息会保存在内核栈中,
上面提到了内核栈,对应着用户栈,在linux中,用户空间和内核空间使用不同的堆栈,每个进程有自己独立的用户空间堆栈,而所有的进程在内核太使用同一个内核栈。内核栈的大小一般是2个page,即8k,但留给程序使用的空间不到8k。当CPU进入中断门时,会从TR寄存器得到TSS段的位置,并从从TSS段从获得SS和ESP的值,从而将当前堆栈指向内核栈。完成堆栈的切换。
要注意的是,当从内核态切换至用户态的时候,用户态的堆栈信息并不从TSS从回去,而是从保存在内核栈中恢复。
PS:TSS是Intel为辅助进程切换而实现的机制,TSS是一种独特的段,存放每个进程的上下文,当需要切换到该进程时,从对应的TSS恢复出进程上下文即可。但linux并未使用该机制。TSS在linux中的主要用途就是保存内核栈的信息,另外,WINE会用到TSS。
阅读(2022) | 评论(0) | 转发(0) |