中断底半部机制之tasklet详解

版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/qq_37600027/article/details/84261519

tasklet 的使用较简单,我们只需要定义tasklet 及其处理函数并将两者关联,例如:

void my_tasklet_func(unsigned long); /*定义一个处理函数*/
DECLARE_TASKLET(my_tasklet, my_tasklet_func, data);
/*定义一个tasklet 结构my_tasklet,与my_tasklet_func(data)函数相关联*/

代码 DECLARE_TASKLETmy_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

猜你喜欢

转载自blog.csdn.net/qq_37600027/article/details/84261519