中断
中断
1 概述:
Linux 的中断处理分为顶半部和底半部,顶半部完成尽可能少得的比较紧急的功能,往往只是简单的完成“登记中断”的工作,
就是就是将底半部处理程序挂到该设备的底半部处理队列中去。但是,也不能僵化的认为linux设备驱动中的中断处理一定分
为两个半部,如果中断要处理的工作本身就很少,则完全可以在顶半部全部完成。查看/proc/interrupts文件可以获得系统
中断的统计信息。
2 中断编程:
1 申请和释放中断
(1) 申请irq
int request_irq (unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname,
void *dev_id)
irq 是要申请的中断号,handler是向系统登记的中断处理函数,irq_flags是中断处理的属性,可以指定中断的触发
方式机处理方式。dev_id 在中断共享时会用到,一般设置为这个设备的结构体或者NULL.
(2) 释放irq
void free_irq (unsigned int irq, void *dev_id); 参数定义与request_irq()相同。
2 使能和屏蔽中断
(1) 屏蔽:void disable_irq (int irq);
void disable_irq_nosync (ing irq);//立即返回
void enable_irq (int irq);
#define local_irq_save (flags)//屏蔽本cpu所有
void local_irq_disable (void) //屏蔽本cpu所有中断
(2) 恢复中断
#define local_irq_restore (flags)
void local_irq_enable (void);
3 底半部机制--实现机制主要有tasklet, 工作队列 和 软中断。
(1) tasklet
void my_tasklet_func (unsigned long);
DECLARE_TASKLET (my_tasklet, my_tasklet_func, data);
/*定义一个tasklet结构my_tasklet, 与my_tasklet_func(data)函数相关联*/
tasklet_schedule (&my_tasklet);
/*使系统在适当的时候调度tasklet注册的函数*/
(2)工作队列
struct work_struct my_wq;
void my_wq_func (unsigned long);
INIT_WORK (&my_wq, (void(*)(void *))my_wq_func, NULL);
/*初始化工作队列并将其与处理函数绑定*/
schedule_work (&my_wq); /*调度工作队列执行*/
(3)软中断(与通常说的软中断(软件指令引发的中断),比如arm的swi是完全不同的概念)
在linux内核中,用softirq_action结构体表征一个软中断,这个结构体包含软中断处理函数指针和传递给该
函数的参数。使用open_softirq()函数可以注册软中断对应的处理函数,而raise_softirq()函数可以触发一
个软中断。
软中断和tasklet 运行与软中断上下文,仍属于原子上下文的一种,而工作队列则运行与进程上下文。因此,
软中断和tasklet处理函数中不能睡眠,而工作队列处理函数中允许睡眠。
local_bh_disable() 和 local_bh_enable()是内核中用于禁止和使能软中断和tasklet底半部机制的函数。
3 实例--s3c2410实时钟中断
参考linux模块,在/drivers/rtc/rtc-s3c.c 和/drivers/rtc/interface.c文件中。