中断是指CPU运行过程中,外设遇到紧急的事物要处理,使得CPU暂停当前指令的执行转去执行中断指令,执行完中断服务程序后又回到当前的指令继续执行。
硬中断是指CPU外设对CPU产生中断。
软中断是指应用程序产生异常,或者人为的产生中断,它是对内核进行中断。
对控制器来说,中断源很多,必须有一个中断控制器来管理这些中断。INTEL8259就是一个典型的中断控制器。
INTEL 中断向量共有256种,分为异常和中断,异常是不可以屏蔽的,也不使用中断控制器。而外设中断是可以通过中断控制器的编程来实现屏蔽的。
LINUX中256个中断向量的分配:
0-31: 异常
32-47:IO设备
48-255:用向量来标识的软中断,LINUX用其中一个来实现系统调用。
8259A 可以控制8个外设中断源。
中断向量表的起始位置
实模式下 0-1K
保护模式 放在IDTR中断描述符寄存器。
相关命令
CALL 调用过程指令
INT 调用中断过程的指令
IRET 中断返回指令
LIDT 加载中断描述表的指令
IDT表项的设置
set_intr_gate
set_trap_gate
set_system_gate
外部中断的设置
for(i = 0; i < NR_IRQS; i++){ |
用户态发生中断,而中断处理程序在内核态,那么需要将用户态的堆栈指针进行压栈。
Linux中的中断描述表 struct iqr_desc_t irq_desc[NR_IRQS].
irq_desc_t结构体中的成员action指向该中断号对应的irqaction结构体链表。
中断处理程序和中断服务例程
中断处理程序:IRQ0X**_interrupt(). 相当于某个中断向量的总服务程序。每一个中断线对应一个中断向量。
为了让多个设备共享一个中断线。内核设置了一个IRQACTION的数据结构。
Struct {
void (*handler) (int, void*, struct pt_regs *);
unsigned long flags;
unsigned long mask;
unsigned char *name;
void *dev_id;
struct irqaction *next;
};
每一个handler就是一个中断服务例程,
在驱动初始化的时候,若使用到了中断,通常要用request_irq建立一个中断服务例程。即申请一个irqaction的结构体。并把它挂载到irq_desc[irq_num]->action链表的下面。这样CPU接收到中断请求后,就可以在irq_desc[]找到该设备的中断服务程序。
IRQn_interrupt()->do_IRQ()->handler_IRQ_event()->action->handler();
do_IRQ->handle_IRQ_event
do{
status |= action->flags;
action ->handler(irq, action->dev_id, regs);
action = action->next;
}while(action);