高庚杓崔始源长得像:Linux内核的中断处理

来源:百度文库 编辑:中财网 时间:2024/04/28 19:52:56

5.4.4 Linux内核的中断处理

对于Linux内核来说,中断信号通常分为两类:硬件中断和软件中断(异常)。每个中断由0~255之间的一个数字来标识。对于中断int0~int31(0x00~0x1f),每个中断的功能由Intel公司固定设定或保留用, 属于软件中断,但Intel公司称之为异常。因为这些中断是在CPU执行指令时探测到异常情况而引起的。通常还可分为故障(Fault)和陷阱(traps)两类。中断int32~int255 (0x20~0xff)可以由用户自己设定。所有中断的分类以及执行后CPU的动作方式见表5-1。

表5-1 中断分类以及中断退出后CPU的处理方式

中断

名称

CPU检测方式

处理方式

硬件

Maskable可屏蔽中断

CPU引脚INTR

清标志寄存器eflags的IF标志可屏蔽中断

Nonmaskable不可屏蔽中断

CPU引脚NMI

不可屏蔽中断

软件

Fault错误

在错误发生之前检测到

CPU重新执行引起错误的指令

Trap陷阱

在错误发生之后检测到

CPU继续执行后面的指令

Abort放弃(终止)

在错误发生之后检测到

引起这种错误的程序应该被终止

在Linux系统中,将int32~int47(0x20~0x2f)对应于8259A中断控制芯片发出的硬件中断请求信号IRQ0~IRQ15(见表5-2),并把程序编程发出的系统调用(system call)中断设置为int128(0x80)。系统调用中断是用户程序使用操作系统资源的唯一界面接口。

表5-2 Linux系统中8259A芯片中断请求发出的中断号列表

中断请求号

中断号

用途

IRQ0

0x20 (32)

8253发出的100Hz时钟中断

IRQ1

0x21 (33)

键盘中断

IRQ2

0x22 (34)

接连从芯片

IRQ3

0x23 (35)

串行口2

IRQ4

0x24 (36)

串行口1

IRQ5

0x25 (37)

并行口2

IRQ6

0x26 (38)

软盘驱动器

IRQ7

0x27 (39)

并行口1

IRQ8

0x28 (40)

实时钟中断

IRQ9

0x29 (41)

保留

IRQ10

0x2a (42)

保留

IRQ11

0x2b (43)

保留(网络接口)

IRQ12

0x2c (44)

PS/2鼠标口中断

IRQ13

0x2d (45)

数学协处理器中断

IRQ14

0x2e (46)

硬盘中断

IRQ15

0x2f (47)

保留

在系统初始化时,内核在head.s程序中首先使用一个哑中断向量(中断描述符)对中断描述符表(Interrupt Descriptor Table,IDT)中所有256个描述符进行了默认设置(boot/head.s,78)。这个哑中断向量指向一个默认的"无中断"处理过程(boot/head.s,150)。当发生了一个中断而又没有重新设置过该中断向量时就会显示信息"未知中断(Unknown interrupt)"。这里对所有256项都进行设置可以有效防止出现一般保护性错误(A gerneal protection fault)(异常13);否则,如果设置的IDT少于256项,那么在一个要求的中断所指定的描述符项大于设置的最大描述符项时,CPU就会产生一个一般保护出错(异常13)。另外,如果硬件出现问题而没有把设备的向量放到数据总线上,此时CPU通常会从数据总线上读入全1(0xff)作为向量,因此会去读取IDT表中的第256项,这样也会造成一般保护出错。对于系统中需要使用的一些中断,内核会在其继续初始化的处理过程中(init/main.c)重新设置这些中断的中断描述符项,让它们指向对应的实际处理过程。通常,异常中断处理过程(int0~int 31)都在traps.c的初始化函数中进行了重新设置(kernl/traps.c,第185行),而系统调用中断int128则在调度程序初始化函数中进行了重新设置(kernel/sched.c,第417行)。

另外,在设置中断描述符表IDT时Linux内核使用了中断门和陷阱门两种描述符。它们之间的区别在于对标志寄存器EFLAGS中的中断允许标志IF的影响。由中断门描述符执行的中断会复位IF标志,因此可以避免其他中断干扰当前中断的处理,随后的中断结束指令iret会从堆栈上恢复IF标志的原值;而通过陷阱门执行的中断则不会影响IF标志。参见第11章中对include/asm/system.h文件的说明