在 Linux 设备驱动中,使用中断的设备需要申请和释放对应的中断,分别使用内核提供的 request_irq()和 free_irq()函数。
1.申请 IRQ
int request_irq(unsigned int irq, void (*handler)(int irq, void *dev_id, struct pt_regs *regs),unsigned long irqflags, const char * devname,void *dev_id);
irq 是要申请的硬件中断号。
handler 是向系统登记的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id 参数将被传递给它。
irqflags 是中断处理的属性,若设置了 SA_INTERRUPT,则表示中断处理程序是快速处理程序, 快速处理程序被调用时屏蔽所有中断, 慢速处理程序不屏蔽; 若设置了 SA_SHIRQ, 则表示多个设备共享中断, dev_id 在中断共享时会用到, 一般设置为这个设备的设备结构体或者 NULL。
request_irq()返回 0 表示成功,返回-INV AL 表示中断号无效或处理函数指针为NULL,返回-EBUSY 表示中断已经被占用且不能共享。
2.释放 IRQ
与 request_irq()向对应的函数为 free_irq(),free_irq()的原型如下:
void free_irq(unsigned int irq,void *dev_id);
free_irq()中参数的定义与 request_irq()相同。
10.3.2 使能和屏蔽中断
下列 3 个函数用于屏蔽一个中断源。
void disable_irq(int irq);
void disable_irq_nosync(int irq);
void enable_irq(int irq);
disable_irq_nosync()与 disable_irq()的区别在于前者立即返回,而后者等待目前的中断处理完成。注意,这 3 个函数作用于可编程中断控制器,因此,对系统内的所有CPU 都生效。
下列两个函数将屏蔽本 CPU 内的所有中断。
void local_irq_save(unsigned long flags);
void local_irq_disable(void);
前者会将目前的中断状态保留在 flags 中,注意 flags 被直接传递,而不是通过指针传递。后者直接禁止中断。
与上述两个禁止中断对应的恢复中断的方法如下:
void local_irq_restore(unsigned long flags);
void local_irq_enable(void);
以上各 local_开头的方法的作用范围是本 CPU 内。
10.3.3 底半部机制
Linux 系统实现底半部的机制主要有 tasklet、工作队列和软中断。