从个人的理解,Linux2.6内核对中断处理程序的现在的处理可以分为两种模式,一种就是上面说的老的模式(非共享中断线),一种属于使用共享中断线的新模式,从其使用的注册中断处理程序的函数中来分析,函数原型如下:
int request_irq(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char * devname,
void * dev_id);
参数1:中断线号
参数2:中断处理程序函数指针
参数3:标志掩码(SA_INTERRUPT, SA_SAMPLE_RANDOM, SA_SHIRQ)
参数4:用于参数3为SA_SHIRQ(共享中断线)的时候,其他为NULL
原来对于计算机设备比较少的时候,可能一个中断线好可以对应一个中断处理程序(非共享中断线),这时候参数4为NULL,没有任何用,但随着计算机设备的增加,一个中断线号对应一个中断处理程序已经不太现实,这个时候就使用了共享的中断线号,多个设备使用同一个中断线号,同一个中断设备线号的所有处理程序链接成一个链表,这样当在共享中断线号的方式下一个中断产生的时候,就要遍历其对应的处理程序链表,但这个中断是由使用同一个中断线号的多个设备中间的一个产生的,不可能链表里面的所有处理程序都调用一遍吧,呵呵,这个时候就该第四个参数派上用场了。
因为多个设备共享同一个中断线号,当中断产生的时候到底是那一个设备产生的中断呢,这个就取决于第四个参数dev_id,这个参数必须是唯一的,也就是能区分到底是那个设备产生的中断,而且从第二个参数可以看出来,这个参数被传入中断处理程序(第二个参数),可以这么理解,当中断产生的时候,如果是共享的中断线号,则对应链表的所有中断处理程序都被调用,不过在每个中断处理程序的内部首先检查(参数信息以及设备硬件的支持)是不是这个中断处理程序对应的设备产生的中断,如果不是,立即返回,如果是,则处理完成,如果链表中没有一个是,则说明出现错误。
下来说说中断处理程序,先看看原型:
static irqreturn_t intr_handler(int irq, void * dev_id, struct pt_regs * regs);
参数1:中断线号
参数2:设备的信息,唯一确定性
参数3:中断之前的处理器寄存器的信息和状态
通过上面的分析,大概可以看到,参数1(中断线号)貌似有点多余,因为如果是非共享的中断线,通过中断线号直接调用处理程序,将这个参数传进去好像没什么用,如果属于共享的中断线,则通过中断线号直接找到对应的中断处理程序链表,挨个遍历,都是一个中断线号,传进去也没用,该不该调用,通过第二个参数来区分,那为什么要保留这个参数呢?答案是历史遗留问题,往后可能越来越没用了,至于为什么是历史遗留问题,可能在没有第二个参数的时候才在第一个上面做了点手脚,既然第二个参数已经添加进去了,第一个的作用就越来越少了。
如果是共享的中断线号,则对应链表的所有中断处理程序都被调用,不过在每个中断处理程序的内部首先检查(参数信息以及设备硬件的支持)是不是这个中断处理程序对应的设备产生的中断,如果不是,立即返回,如果是,则处理完成,如果链表中没有一个是,则说明出现错误。