中断就是程序在正常执行过程中被打断,暂时停止运行当前代码而跳转去执行相应的服务代码,在完成相应的服务任务之后继续执行之前被打断的程序。在驱动程序中,硬件在需要时向内核发出信号。相比轮询模型而言,中断模型避免了让cpu周期性地重复执行,节省了cpu时间,提高了效率。
Linux下的中断体系机构或者说当中断来临后,cpu做了哪些工作,通过分析内核代码,可以得出以下总结,即中断体系结构:
当中断来临,cpu中断处理流程:
a.中断向量调用入口函数asm_do_IRQ,传入中断号irq
b.asm_do_IRQ函数根据终端号irq调用irq_desc[irq].handle_irq,它是这中断处理函数的入口,对于电平触发中断,入口函数为handle_level_irq,对于边沿触发中断,入口函数为handle_edge_irq
c.入口函数首先清楚中断,若入口函数是handle_level_irq要屏蔽中断
d.逐个调用用户在irq_desc[irq].action链表中注册的中断处理函数
e.入口函数如果是handle_level_irq要打开中断
在Linux系统下,每个(类)中断都对应着一个irq_desc结构体,这个结构体中包含有中断的名称、标志、状态,并且包含着中断的入口函数。在irq_des结构中,还包含有一个action结构,用户注册的每一个中断处理函数都会对应着一个action,一个中断可以有多个中断处理函数,这些多个处理函数则是会链接成一个链表。
中断的体系结构已经由内核制定好,当在驱动中需要使用中断模型时,只需要向内核注册相应中断的处理函数和触发标志等等,在卸载时注销中断即可。
用户注册中断处理函数:
int request_irq(unsigned int irq, irq_handler_t handler,unsigned long irqflags, const char *devname, void *dev_id)//根据中断号找到irq_desc数组项,,然后在action链表中添加一个表项。
//irqflags是中断的标志,在linux/interrupts.h中有宏定义
//irq_handler_t handler是用户自己定义的中断处理函数
注销中断:
void free_irq(unsigned int irq, void *dev_id)//注销中断
void disable_irq(unsigned int irq)//禁止中断
void enable_irq(unsigned int irq)//使能中断
通过以上这几个函数,则可以为驱动程序添加中断服务。