博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux中断定义与初始化
阅读量:4212 次
发布时间:2019-05-26

本文共 3539 字,大约阅读时间需要 11 分钟。

1.中断的分类

早期以及一般情况下,我们所说的中断即指由外设所产生的中断。随着计算机的迅速发展,中断不再仅仅局限于外部设备,CPU本身也会产生中断,不过我们将这种中断称为异常。

对于x86体系结构而言,中断可以分为两大类:同步中断和异步中断。同步中断即我们上面所说的异常,它是由 CPU 在执行非法命令时所产生的。之所以称为同步,是因为这种中断请求信号与代码指令同步执行,也就是说只有在一条指令执行完毕后 CPU 才会发出中断,而不是发生在代码指令执行期间。而异步中断即由外部设备产生的中断,这种中断可以随时发生,习惯上,我们将异步中断仍然称为中断。

中断可分为可屏蔽中断(Maskable interrupt)和不可屏蔽中断(Nomaskable interrupt)。异常可分为故障(fault)、陷阱(trap)、终止(abort)三类。

可屏蔽中断主要是针对外部设备所产生的中断信号,不可屏蔽中断一般是指计算机内部硬件产生的中断。由于异常是CPU发出的中断信号,与中断控制器(下文有解释)无关,因此异常不能被屏蔽。那么,异常和不可屏蔽中断有些相似点:它们均与外部设备无关,并且均不能被屏蔽。

2.中断控制器

中断控制器可分为可编程中断控制器(Programmable Interrupt Controller,PIC)和高级可编程中断控制器(Advanced Programmable Interrupt Controller,APIC)。前者仅可用于单处理器(Uni-processor)平台,后者则可用于多处理器(Mutiliple Processor)平台。

传统的PIC都是通过两片级联的8259A来管理和控制15个由外部设备所产生的中断源。由下图可看到,每片8259A芯片最多可管理8个中断源。但由于两片8259A芯片的级联,即从片的INT输出端与主片的2号(第三条线)中断线相连接,所以总共可以管理15个中断源。

外设和中断控制器上每根相连的线被称为中断线(也称为IRQ线)。对这些中断线进行编号就形成了中断号。IRQn线所对应的中断号即为n。当外部设备产生中断时,就通过中断线向系统发出中断请求(Interrupt ReQuirement)。由于中断控制器只能控制15个中断源,而如今的外设又日益剧增,因此就出现了对各外设共享一条中断线的情况,即中断共享(后文会有详细解释)。

上面已经说过,外部设备的中断请求可以被屏蔽,但是具体体现到硬件上是如何做到的?在每个8259A芯片上都有一个8位的中断屏蔽寄存器,每一位对应一条中断线。在对应为上置1则可屏蔽此条中断线;相反置0则可启动此条中断线。

需要说明的是,现在大多数计算机都使用的是APIC,可以通过查看/proc/interrupts文件获取中断控制器的名称。之所以将传统的8259A作为PIC的举例来学习,最大的原因还是因为它非常的经典,就如同古董——8086处理器一样。通过查看/proc/interrupts文件,可以发现APIC的中断号并不止15个(但即便是这样,还需要共享中断)。

3.中断向量

x86体系结构支持256种中断,即256个中断源。将这些中断源按照0到255的顺序对每种中断进行编号,这个编号叫做中断向量,通常使用8位无符号整数来存储这个向量。中断号和中断向量存在一对一的映射关系。

中断号和中断向量是两个不同的概念。当I/O设备把中断信号发送给中断控制器时,与之关联的是一个中断号;而当中断控制器将该中断信号传递给CPU时,与之关联的是一个中断向量。也就是说,中断号是以中断控制器的角度而言的;而中断向量则是以CPU的角度而言的。中断号和中断向量存在一对一的映射关系。

通常,Intel将编号为0~31的向量分配给异常和非屏蔽中断,这部分向量是固定的。因此在8259A默认情况下,中断号n所对应的中断向量为n+32。

4.中断服务例程

在响应一个具体的中断时,内核会执行一个函数,该函数被称为中断服务例程(Interrupt Service Routine,ISR)。每一个设备的驱动程序中都会定义相关的中断服务例程。从下面的代码可以看到,中断服务例程有两个参数,分别为int型和void指针型。并且返回值为irqreturn_t。

01 //linux/include/linux/interrupt.h
02  98typedef irqreturn_t (*irq_handler_t)(intvoid *);
03 //linux/include/linux/irqreturn.h
04  10enum irqreturn {
05  11        IRQ_NONE,
06  12        IRQ_HANDLED,
07  13        IRQ_WAKE_THREAD,
08  14};
09  15
10  16typedef enum irqreturn irqreturn_t;

由于irqreturn_t是一个枚举类型,因此本质上为整形。并且IRQ_NONE,IRQ_HANDLED,IRQ_WAKE_THREAD的值一次为0,1,2。IRQ_NONE表示不处理所收到的中断请求;IRQ_HANDLED表示接收到了有效的中断请求,并且作出了正确的处理(这一点在后文中有详细讨论)。

需要注意的是,当一个中断服务例程正在执行的时候,该中断所在所有处理器上的都会被屏蔽,以免继续接受同一条中断线上的另一个新的中断。

x86的中断处理过程

由于中断是开着的,所以当执行完一条指令后,cs和eip这对寄存器中已经包含了下一条将要执行的指令的逻辑地址。在处理那条指令之前,控制单元会检查在运行前一条指令时是否发生了一个中断或异常。如果发生了一个中断和异常,那么控制单元执行下列操作:

1. 确定与中断或异常关联的向量i(0≤ i ≤255)

2. 读由idtr寄存器指向的IDT表中的第i项。

3. 从gdtr寄存器获得GDT的基地址,并在GDT中查找,以读取IDT表项中的选择符标识的段描述符。这个描述符指定中断或异常处理程序所在的段的基地址。

4. 确信中断是由授权的(中断)发生源发出的。首先将当前特权级CPL(存放在cs寄存器的低两位)与段描述符(存放在GDT中)的描述符特权级DPL比较。如果CPL小于DPL,就产生一个“通常保护”异常,因为中断处理程序的特权级不能低于引起中断的程序的特权。对于编程异常,则做进一步的检查:比较CPL与处于IDT中的门描述符的DPL,如果DPL小于CPL,就产生一个“通常保护”异常,这最后一个检查可以避免用户应用程序访问特殊的陷阱门和中断门。

5. 检查是否发生了特权级的变化,也就是说,CPL是否不同于所选择的段描述符的DPL。如果是,控制单元必须开始使用与新的特权级相关的栈,通过执行以下步骤来保证这一点:

A. 读tr寄存器,以访问运行进程的TSS段。

B. 用与新特权级相关的栈段和栈指针的正确值装载ss和esp寄存器。这些值可以在TSS中找到。

C. 在新的栈中保存ss和esp以前的值,这些值定义了与旧特权级相关的栈的逻辑地址。

6. 如果故障已发生,用引起异常的指令地址装载cs和eip寄存器,从而使得这条指令能再次被执行。

7. 在栈中保存eflag、cs和eip的内容。

8. 如果异常产生了一个硬件出错码,则将它保存在栈中。

9. 装载cs和eip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量字段。这些值给出了中断或者异常处理程序的第一条指令的逻辑地址。

  控制单元所执行的最后一步就是跳转到中断或异常处理程序。换句话说,处理完中断信号后,控制单元所执行的指令就是被选中处理程序的第一条指令。

上面的处理过程的描述摘自<<深入理解内核>>,其中有几点值得注意的地方:

1:通过门后,只能提高运行级别.就像上面所述的 “当前特权级CPL(存放在cs寄存器的低两位)与段描述符(存放在GDT中)的描述符特权级DPL比较。如果CPL小于DPL,就产生一个“通常保护”异常”.在中断处理中,通常把IDT中的相应段选择符设为__KERNEL_CS.即最高的运行级别

2:上面C所述:“在新的栈中保存ss和esp以前的值,这些值定义了与旧特权级相关的栈的逻辑地址”,那ss,esp以前的值是如何找到的呢?应该是从TSS中.在中断发生的时候,如果检测到运行级别发生了改了,将寄存器SS,ESP中的值保存进TSS的相应级别位置.再加载新的SS,ESP的值,然后从TSS中取出旧的SS,ESP值,再压栈.

3:堆栈的改变,如下图所示:

转载地址:http://ojkmi.baihongyu.com/

你可能感兴趣的文章
Oracle 11g 新特性 -- 自动诊断资料档案库(ADR) 说明
查看>>
Oracle 11g 新特性 -- RMAN Data Recovery Advisor(DRA) 说明
查看>>
CSDN博客之星 投票说明
查看>>
Oracle wallet 配置 说明
查看>>
/dev/sdxx is apparently in use by the system; will not make a filesystem here! 解决方法
查看>>
RMAN-01009: syntax error: found "dot" 解决方法
查看>>
Oracle smon_scn_time 表 说明
查看>>
VBox fdisk 不显示 添加的硬盘 解决方法
查看>>
Secure CRT 自动记录日志 配置 小记
查看>>
RMAN RAC 到 单实例 duplicate 自动分配通道 触发 ORA-19505 错误
查看>>
mysql 随机分页的优化
查看>>
SQL SERVER中判断某个字段是否包含大写字母
查看>>
修改master库文件路径
查看>>
拷贝增量文件
查看>>
mysql中的 skip-name-resolve 问题
查看>>
删除最后一次的备份文件vbs
查看>>
vbs 实现压缩文件夹为zip文件
查看>>
在VBS中,SET的用法
查看>>
组策略合理限制VBS文件
查看>>
VBS不支持跨盘操作
查看>>