Linux的中断和传统的单片机中断还不太一样,它把中断分为了上中断和下中断。
做过裸机开发的同学应该都知道,中断中应该尽量少做高延时的操作,这样会导致其他中断被挂起,响应不及时。另外由于挂起的任务过多,占用的栈也增加,容易造成栈溢出的错误。
举个最简单的例子,我们的网卡驱动程序在收到网络数据包后,会产生一个中断,由于网卡寄存器缓存区有限,我们应该在中断中立刻将接收到的数据包拷贝到我们的接收缓存区,然后退出中断,后续的耗时操作与中断无关。
所以linux区分上下中断也是为了实现上述的操作罢了,上中断做拷贝操作,后续的耗时操作放到下中断去解决即可。
1、 上半部中断的注册使用
头文件:<linux/interrupt.h>
int request_irq(unsigned int irq,
irq_handler_t handler,
unsigned long irqflags,
const char *devname,
void *dev_id)
功能:注册一个中断处理程序,并激活中断线
第一个参数 irq 表示要分配的中断号,这个是根据你的芯片手册来设置
第二个参数 handler 是一个指针,指向处理这个中断的实际中断处理程序,只要操作系统接收到中断,这个函数就被调用。
第三个参数 irqflags 是一个或多个标志的掩码,用来设置中断的属性,如IRQF_DISABLED表示处理中断期间,其他中断被屏蔽。
第四个参数 devname 是与中断线相关的设备名字,会被 /proc/irq和/proc/interrupt使用。
第五个参数 dev_id 是用于共享中断线的,当使用完中断后,会主动释放掉这个dev_id 的中断权,若不需要可填NULL。
void free_irq(unsigned irq, void* dev)用于注销掉相应的中断处理程序,并释放中断线。
一个上中断处理函数:
中断中会用到大量的自旋锁,主要是防止被休眠,影响实时性。
static irqreturn_t xxx_handler(int irq, void *dev)
{
spin_lock(&xxx_lock);
//do something
spin_unlock(&xxx_lock);
return IRQ_HANDLED;
}
2、下半部中断的使用
下中断的实现方式比较多,目前主要分为以下几种:
1、软中断
2、任务队列
3、tasklet
可以通过上中断来触发以上三种下中断,实现任务的下中断处理。