背景:中断不属于进程上下文,所以不能被内核调度,如果进入了中断处理函数,就只能将其执行完毕,不能被打断,这样带来的一个问题是如果在中断处理函数中执行耗时操作,就会极大的影响系统性能,为了解决这个问题,Linux内核中提出了中断顶半部和`底半部(bottom half)的概念,对于耗时的中断处理程序,将重要的、必要的操作放在顶半部执行,这部分和传统的中断概念一样,一旦开始就必须执行完毕;将中断处理程序中耗时的,不那么紧要的操作放在底半部,防止整个中断处理程序过多的占用系统资源。
Linux内核提供的3种中断底半部机制:工作队列,tasklet,软中断。其中软中断机制是内核底层的机制,包括定时器,异步通知等很多机制都是基于软中断,开发者不应该直接操作
参考链接:https://www.cnblogs.com/xiaojiang1025/p/6388603.html
1、 声明自己的tasklet:
#include <linux/interrupt.h>
struct tasklet_struct
{
struct tasklet_struct *next;/*链表中的下一个tasklet*/
unsigned long state;/*tasklet的状态*/
atomic_t count;/*引用计数器*/
void (*func)(unsigned long);/*tasklet处理函数*/
unsigned long data;/*给tasklet处理函数的参数*/
};
state成员只能是0、TASKLET_STATE_SCHED和TASKLET_STATE_RUN之间取值。
count成员只有为0时,tasklet才被激活,并且在被设置为挂起状态时,该tasklet才能执行。
void tasklet_init(my_tasklet, tasklet_handler,dev) /*动态方式创建*/
my_tasklet//即为声明的tasklet
tasklet_handler//绑定的tasklet处理程序
dev//处理程序的参数
2、 编写tasklet处理程序
void tasklet_handler(unsigned long data);
注意事项:因为是靠软中断实现,所以tasklet不能睡眠,因此不能在tasklet中使用信号量或其他阻塞式函数。
3、 调度你的tasklet
tasklet_schedule(&my_tasklet);/*把my_tasklet标记为挂起*/
在tasklet被调度后,只要有机会它就会被尽早运行。