tasklet机制与softirq
1、初始化
静态:DECLARE_TASKLET(name, func, data);
动态:
struct tasklet_struct
{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long);
unsigned long data;
};
void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data)
{
t->next = NULL;
t->state = 0;
atomic_set(&t->count, 0);
t->func = func;
t->data = data;
}
struct tasklet_struct mytasklet; // 定义tasklet_struct结构体
tasklet_init(&mytasklet, tasklet_handler, &mydata); // 初始化 data可以是 变量/函数/结构体等的地址,如struct mydata mydata;
void tasklet_handler(unsigned long data) { // callback函数
struct mydata *p = (struct mydata *)data;
...
}
tasklet_schedule(&mytasklet); // 初始化之后需要交给tasklet_schedule来调度
tasklet_kill(&mytasklet); // 移除tasklet
与softirq的不同:tasklet只能在一个CPU上运行,而同一个softirq可以同时在多个CPU core上运行;
软中断的静态分配的,内核编译好之后就不能改变,但tasklet就要灵活许多,比如动态加载模块
所以在不需要并行运行软中断时就应该选择tasklet
共同点:tasklet与softirq都不能睡眠,不能阻塞,只能被其他中断的上半部分打断
工作队列可以睡眠,并且可以具有更大的延时执行,tasklet代码必须以原子方式执行,会在很短的时间很快地执行
工作队列是在进程上下文执行,也就是执行过程中运行其他进程抢占;而tasklet是在中断上下文中运行,只有其他中断响应可以打断tasklet的运行, 保证了原子操作。