一、Linux中断处理程序框架
Linux将中断处理程序分为2部分:top half, bottom half. top half 完成尽可能少的比较紧急的功能,往往只是简单地读取寄存器中的中断标志位并清除中断标志后进行“登记中断”的工作,将bottom half处理程序挂到该设备的bottom half 执行队列中去。bottom完成中断事件的绝大多数任务,几乎完成中断处理程序的所有工作。
二、中断编程
在linux设备驱动中,使用中断的设备需要申请和释放对应的中断,分别使用内核提供的request_irq()和free_irq()函数。
1.申请IRQ
typedef irqreturn_t (*irq_handler_t)(int, void *);
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev);
2.释放IRQ
void free_irq(unsigned int irq, void *dev_id);
3.屏蔽中断
void disable_irq(int irq);
void disable_irq_nosync(int irq);
void enable_irq(int irq);
//屏蔽本cpu内的所有中断
void local_irq_save(unsigned long flags);
void local_irq_disable(void);
|
三、底半部机制
Linux系统实现底部的机制主要有tasklet,工作队列和软中断
1. tasklet
void my_tasklet_func(unsigned long);//定义一个处理函数
/*定义一个tasklet结构my_tasklet,与my_tasklet_func函数关联, data 是传入my_tasklet_func函数的参数*/
DECLEAR_TASKLET(my_tasklet,my_tasklet_func, data);
在需要调度bottom half的时候,调用函数:
tasklet_schedule(&my_tasklet);
2. 工作队列
struct work_struct my_wq;/*定义一个工作队列*/
void my_wq_func(unsigned long);/*定义一个处理函数*/
/*通过INIT_WORK()可以初始化这个工作队列执行函数并将工作队列与处理函数绑定*/
INIT_WORK(&my_wq, (void (*)(void *)) my_wq_func, NULL);
在需要调度工作队列的时候,调用函数:
schedule_work(&my_wq);
3. 软中断
在linux内核中,用softirq_action结构体表征一个软中断,这个结构体中包含软中断处理函数指针和传递给该函数的参数。使用open_softirq()函数可以注册软中断对应的处理函数,而 raisesoftirq()函数可以触发一个软中断。
区别:软中断和tasklet仍然运行于中断上下文,而工作队列则运行于进程上下文。因此,软中断和tasklet处理函数中不能睡眠,而工作队列处理函数中允许睡眠。local_bh_disable() ,local_bh_enable()是内核中用于禁止和使能软中断和tasklet底半部机制函数。
|
阅读(880) | 评论(0) | 转发(0) |