您的位置:首页 > 运维架构 > Linux

深入理解Linux内核个人小结4---中断和异常

2012-10-01 10:00 621 查看
一. 中断和异常综述

中断分为两种:

同步中断:又称之为异常,是不可屏蔽中断。

异步中断: 即通常的中断,部分可屏蔽。且异常有对应的出错码。

内核控制路径: 中断发生时正在运行的程序在内核态的执行。

中断向量:8位无符号整数,用来标识中断和异常。其中非屏蔽的中断和异常对应的中断向量是固定的。而可屏蔽的中断向量可通过PIC(可编程中断控制器)进行编程来改变。其中中断向量的前32个被异常所占用(0~19已用,20~31保留),128号为系统调用。

IRQ与PIC的交互过程:

1.PIC监视IRQ线,检查产生的信号,若同时在两条以上的IRQ线上产生信号则选择编号较小的。

2.PIC将接受的信号转换成中断向量,并将其放在I/O端口,产生一个INTR中断,待CPU读取中断向量后清INTR中断;然后返回第一步。

中断禁止与中断屏蔽的区别:

中断禁止可选局部且中断不会丢失,而屏蔽则是全局的期间会导致中断丢失。

二. 中断和异常的硬件处理

中断描述符表:IDT 类似GDT都是8个字节。 基址存放于寄存器IDTR中。共三种:任务们描述符,中断门描述符,陷阱门描述符。

硬件处理过程:

1. 确定对应的中断向量i

2, 经IDTR 读取IDT中的第i项,从中可得到相应的中断(异常)处理程序的段基址及偏移量。

3. 相关的权限检查

4. 保存相应的寄存器的值到堆栈 如 cs/eip,若是异常还应当将出错码压入到堆栈中,将处理程序的基址/偏移量压入cs/eip中,进行处理

5. 处理结束返回,弹出出错码;将事先保存在堆栈的cs/eip的值放入cs/eip寄存器,继续开始正常运行。

中断与异常嵌套

中断可以嵌套,但其间不能发生进程切换。因嵌套时相应信息都保存在内核态堆栈,若进程切换将导致相应内容被换出内核。

异常最多发生两层的嵌套,(因异常大都发生在用户态),由于缺页中断发生在内核态,故最多可发生两层嵌套且最后一层为缺页中断。

三. 异常和终端的Linux下的处理

异常处理: 异常发生时,CPU或其他产生一个异常,对应的异常处理程序(相关工作有硬件进行处理)向当前进程发送一个信号,此进程采取下列步骤进行处理

1. 内核态堆栈中保存大多数寄存器的值。

2. 用高级C语言函数处理异常。

3.ret_from_exception()函数跳出异常。

中断处理:

1. 在内核态堆栈中保存IRQ的值及寄存器的内容

2. 给正在为IRQ服务的PIC发送一个应答,允许PIC进一步发出中断

3. 执行此IRQ的所有设备的中断服务例程(ISR)

4. ret_from_intr()函数跳出中断。

软中断,tasklet与工作队列:

为了让中断处理的更快,同时要完成相应的全部工作。根据具体没内容将中断分为两部分:上半部分(中断处理部分)和下半部分(推后处理部分)。上半部分需要立 即 执行并且有严格的时间限制,这些工作是在其他所有中断被禁止是完成的,剩余部分推迟到下半部分,下半部分的任务是执行与中断处理密切相关但中断处理程序本身 不执行的工作。在Linux2.6内核中存在三种不同形式的下半部分实现机制: 软中断,tasklet和工作队列。

软中断:

编译期间静态分配的,最多有32个软中断,软中断之间不会抢占,唯一可抢占软中断的是中断处理程序。

tasklet:基于两种软中断实现的 HI_SOFIRQ和TASKLET_SOFTIRQ,无数量限制可动态增加,同类型不可并发执行,而不同种类可以并发执行。

工作队列:由内核线程去执行,允许重新进行带哦度,如可以睡眠阻塞等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: