模块在使用中断前要先申请一个中断通道(或称中断请求IRQ),然后在使用后释放该通道。这样可以共享中断信号线
在<linux/sched.h>中,声明了该接口:
int request_irq( unisgned intirq, //要请求的中断号。
void (*handler)(int, void,struct pt_regs *),//要安装的中断处理函数指针。
unsinged longflags, //与中断管理有关的位掩码选项。
const char*dev_name, //传递的字符串,用在/proc/interrups中显示中断的拥有者。
void *dev_id);
参数说明:
void *dev_id
这个指针用于共享的中断信号线。它是唯一的标示符,在中断信号线空闲时可以使用它。驱动程序也可以使用它指向驱动程序自己的私有数据区,用于识别是那个设备产生了中断。在没有强制使用共享方式时,dev_id可以设置为NULL,但用于指向设备的数据结构是一个好的思路。传递给request_irq的dev_id参数,会在中断发生时作为参数传递给中断处理程序。
request_irq返回值,为0时表示成功,负值表示错误码。返回-EBUSY表示中断信号线已经被占用了。
××××××何时安装中断处理程序
可以在模块初始化时安装,但这不是很好的方式,因为中断信号线是非常有限的资源。所以正确的方式是在设备第一次打开,硬件被告知产生中断之前。
××××××与中断相关的/proc文件系统
/proc/interrupts中,显示了系统中断的快照。只显示已安装的中断。
/proc/stat中的intr行也显示了系统中的中断发生情况。第一个数是系统所有中断的总数。其后的数都代表了每个中断发生的次数。
×快速和慢速处理程序
老版本的内核中,区分“快速”和“慢速”中断。慢速中断会花费比较长的时间,其要求处理器可以重启中断。而现在的内核中,则只有快速中断了。当它执行时,当前处理器上的中断都被禁用了。其他的处理器仍然可以处理中断。
##快速处理程序在微处理器的中断报告被禁用的状态下运行,且在中断控制器中,正在处理的中断类型被禁用。但是,中断处理程序可以通过调用sti来启用处理器上的中断报告。
##慢速处理程序在启用了处理器的中断报告的状态下运行,并且在中断控制器上,正在处理的中断被禁止。
×实现中断处理程序
中断处理程序比较特殊的地方是:其运行于中断期间,所有其行为会受到一些限制:其不是运行在任何的进程空间,所以不能和用户空间通讯。其也不能做任何可能发生休眠的操作。
中断处理程序的作用就是将有关中断接收的信息反馈给设备,对数据进行操作。如果中断通知进程等待的事件已经发生,要唤醒在该设备上睡眠的进程,如使用wake_up_interrupts()。
如果处理程序要一个长时间的计算任务,那最好的方法是使用tasklet或任务队列,以使在更安全的时间内调度计算任务--此时,所有的中断都开着。
×启用和禁用中断
可以使用sti/cli来启用/禁用所有的中断,但它们的问题是,控制了所以的系统中断。在驱动中,通常要为自己的irq信号启用或禁用中断报告。内核在<asm/irq.h>中提供了3个函数:
voiddisable_irq(int irq)
voiddisable_irq_nosync(int irq)
voidenable_irq(int irq)
底半处理
Linux通常将中断处理程序分成两部分来实现,以解决速度要求和工作计算两要求这对矛盾。底半部(bottomhalf)是被顶半部(tophalf)调度,在稍后的更安全的时候执行的例程。
在2.3内核及以后,使用tasklet来实现底半部处理。在老的内核中,使用老的称为BH机制实现。
诸如以下函数:
request_irq()/*给给定的中断源安装中断处理程序*/;
free_irq()
/*释放分配给已定中断的内存*/;
enable_irq() /*调用中断控制函数使给定中断链有效*/ ;
disable_irq()/*使定义中断链失效*/
为什么已经注册的中断在/proc/interrupts文件下不存在??????????????????????????