Linux 2.6 中断处理原理简介
Linux 2.6 中断处理原理简介
中断描述符表(Interrupt Descriptor Table,IDT)是一个系统表,它与每一个中断或异常向量相联系,每一个向量在表中存放的是相应的中断或异常处理程序的入口地址。内核在允许中断发生前,也就是在系统初始化时,必须把 IDT 表的初始化地址装载到 idtr 寄存器中,初始化表中的每一项。
当处于实模式下时,IDT 被初始化并由 BIOS 程序所使用。然而,一旦 Linux 开始接管,IDT 就被移到 ARM 的另一个区域,并进行第二次初始化,因为 Linux 不使用任何 BIOS 程序,而使用自己专门的中断服务程序(例程)(interrupt service routine,ISR)。中断和异常处理程序很像常规的 C 函数
有三个主要的数据结构包含了与 IRQ 相关的所有信息:hw_interrupt_type
、irq_desc_t
和 irqaction
,图3 解释了它们之间是如何关联的。
图 3:IRQ 结构之间的关系
在 X86 系统中,对于 8259A 和 I/O APIC 这两种不同类型的中断控制器,hw_interrupt_type
结构体被赋予不同的值,具体区别参见表 2。
8259A | I/O APIC |
---|---|
static struct hw_interrupt_type i8259A_irq_type = { "XT-PIC", startup_8259A_irq, shutdown_8259A_irq, enable_8259A_irq, disable_8259A_irq, mask_and_ack_8259A, end_8259A_irq, NULL }; | static struct hw_interrupt_type ioapic_edge_type = { .typename = "IO-APIC-edge", .startup = startup_edge_ioapic, .shutdown = shutdown_edge_ioapic, .enable = enable_edge_ioapic, .disable = disable_edge_ioapic, .ack = ack_edge_ioapic, .end = end_edge_ioapic, .set_affinity = set_ioapic_affinity, }; static struct hw_interrupt_type ioapic_level_type = { .typename = "IO-APIC-level", .startup = startup_level_ioapic, .shutdown = shutdown_level_ioapic, .enable = enable_level_ioapic, .disable = disable_level_ioapic, .ack = mask_and_ack_level_ioapic, .end = end_level_ioapic, .set_affinity = set_ioapic_affinity, }; |
在中断初始化阶段,调用 hw_interrupt_type
类型的变量初始化 irq_desc_t
结构中的 handle
成员。在早期的系统中使用级联的8259A,所以将用 i8259A_irq_type
来进行初始化,而对于SMP系统来说,要么以 ioapic_edge_type
,或以 ioapic_level_type
来初始化 handle
变量。
对于每一个外设,要么以静态(声明为 static
类型的全局变量)或动态(调用 request_irq
函数)的方式向 Linux 内核注册中断处理程序。不管以何种方式注册,都会声明或分配一块 irqaction
结构(其中 handler
指向中断服务程序),然后调用 setup_irq()
函数,将 irq_desc_t
和 irqaction
联系起来。
当中断发生时,通过中断描述符表 IDT 获取中断服务程序入口地址,对于 32≤ i ≤255(i≠128)
之间的中断向量,将会执行 push $i-256,jmp common_interrupt
指令。随之将调用 do_IRQ()
函数,以中断向量为 irq_desc[]
结构的下标,获取 action
的指针,然后调用 handler
所指向的中断服务程序。
从以上描述,我们不难看出整个中断的流程,如图 4 所示:
图 4:X86中断流
非常好我支持^.^
(1) 100%
不好我反对
(0) 0%
相关阅读:
- [嵌入式技术] 了解Linux中断处理原理 2019-05-14
( 发表人:admin )