1.中断概念
中断时一种电信号,由硬件设备产生,然后再由中断控制器向处理器发送相应的信号。处理器一经检测到该信号,便中断自己当前正在处理的工作,转而去处理中断。此后,处理器会通知操作系统已经产生中断。不同的设备,对应的中断不同,而每个中断都通过一个唯一的数字标识,这些值通常被称为中断请求线。
2.Linux2.6中断处理原理
- 获取中断号:中断处理程序的第一步要做两件事:
* 将中断号压栈
* 将当前寄存器信息压栈
- 中断串行化:将多个cpu同时产生的某一中断进行串行化
- 关中断条件下的中断处理:中断处理函数总是在关中断的情况下进行
- 开中断条件下的软中断
- 开中断下的tasklet:软中断很少直接被使用,开中断情况下进行的处理过程一般是由tasklet机制完成
3.Linux中断处理程序架构
- Linux系统将中断程序分成上半部和下半部:
* 顶半部:完成尽可能少,比较紧急的功能。往往只是简单读取寄存器中的中断状态并清除中断标志后就进行登记中断工作
* 底半部:中断处理大部分工作都在底半部完成。主要机制有:tasklet, 工作队列, 软中断
- tasklet
* 定义tasklet机器处理器,并将两者关联
void my_tasklet_func(unsigned long) DECLARE_TASKLET(my_tasklet, my_tasklet_func, data)
* 调度
tasklet_schedule(&my_tasklet)
- 工作队列
* 定义一个工作队列
struct work_struct my_work;
void my_wq_functon(struct work_struct *work);
* 在初始化函数中通过INIT_WORK()初始化工作队列并将工作队列与处理函数绑定
INIT_WORK(&my_work, (void *)my_wq_func);
* 在适当的地方调度工作队列,一般在中断的上半部调度
schedule_work(&my_work);
- Linux 2.6中断API
* request_irq:向内核注册一个中断服务函数
* free_irq:从内核注销一个中断服务函数
* disable_irq:关闭指定中断,并等待中断服务函数运行结束才会返回
* disable_irq_nosync:关闭指定中断,不等待中断服务函数结束,调用完该函数立即返回
* enable_irq:打开指定中断
- 中断共享:指多个设备共享一根中断线的情况,中断共享使用方法如下:
* 在申请中断时,使用IRQF_SHARED标志
* 在中断到来时,会遍历共享此中断的所有中断处理程序