tasklet 的使用较简单,我们只需要定义tasklet 及其处理函数并将两者关联,例如:
void my_tasklet_func(unsigned long); /*定义一个处理函数*/
DECLARE_TASKLET(my_tasklet, my_tasklet_func, data);
/*定义一个tasklet 结构my_tasklet,与my_tasklet_func(data)函数相关联*/
代码 DECLARE_TASKLET(my_tasklet,my_tasklet_func,data)实现了定义名称为my_tasklet 的tasklet并将其与my_tasklet_func()这个函数绑定,而传入这个函数的参数为data。my_tasklet的类型为struct tasklet_struct。
在需要调度 tasklet 的时候引用一个tasklet_schedule()函数就能使系统在适当的时候进行调度运行,如下所示:
tasklet_schedule(&my_tasklet);
使用 tasklet 作为底半部处理中断的设备驱动程序模板如下所示(仅包含与中断相关的部分)。
/*定义tasklet 和底半部函数并关联*/
void xxx_do_tasklet(unsigned long);
DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0);
/*中断处理底半部*/
void xxx_do_tasklet(unsigned long)
{
...
}
/*中断处理顶半部*/
irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
...
tasklet_schedule(&xxx_tasklet);/*在合适的时机调用底半部*/
...
}
/*设备驱动模块加载函数*/
int __init xxx_init(void)
{
...
/*申请中断*/
result = request_irq(xxx_irq, xxx_interrupt, SA_INTERRUPT, "xxx", NULL);
...
}
/*设备驱动模块卸载函数*/
void __exit xxx_exit(void)
{
...
/*释放中断*/
free_irq(xxx_irq, xxx_interrupt);
...
}
上述程序在模块加载函数中申请中断(第24 行),并在模块卸载函数中释放它(第33 行)。
对应于xxx_irq 的中断处理程序被设置为xxx_interrupt()函数,在这个函数中,第15 行的tasklet_schedule(&xxx_tasklet)调度的tasklet 函数xxx_do_tasklet()在适当的时候得到执行。上述代码第 12 行显示中断处理程序顶半部的返回类型为irqreturn_t,它定义为int,中断处理程序顶半部一般返回IRQ_HANDLED。