Yuhang Zheng

第二十四节、中断下文之tasklet

N 人看过

本节用于介绍中断下文之tasklet

一、tasklet 相关知识点

1、什么是tasklet?

tasklet是中断处理中断下文常用的一种方法,tasklet是一种特殊的软中断。处理中断下文的机制还有工作队列和软中断。

2、怎么使用tasklet来设计中断下文?

Linux把中断分成俩个部分,一个是上半部分,一个是下半部分,在上半部分我们只处理紧急的事情,同时可以调用tasklet来启动中断下文,比较耗时间的就要放到下文来处理,调用tasklet以后,tasklet绑定的函数并不会立马执行,而是出中断以后,经过一个很短的不确定时间在来执行。

3.tasklet定义

tasklet 由 tasklet_struct 结构表示,每个结构体单独代表一个tasklet

文件位置路径:include/linux/interrupt.h

struct tasklet_struct
{
        struct tasklet_struct *next;    //链表中的下一个tasklet,方便管理和设置tasklet
        unsigned long state;            //tasklet的状态
        atomic_t count;                    //表示tasklet是否出在激活状态,如果是0,就处在激活状态,如果非0,就处在非激活状态
        void (*func)(unsigned long);    //结构体中的func 成员是tasklet的绑定函数,data是它唯一的参数
        unsigned long data;                //函数执行的时候传递的参数
};

二、tasklet 相关函数

<1>tasklet_schedule函数

作用:调度tasklet

函数原型:

文件位置路径:include/linux/interrupt.h

extern void __tasklet_schedule(struct tasklet_struct *t);

static inline void tasklet_schedule(struct tasklet_struct *t)
{
        if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
                __tasklet_schedule(t);
}
//参数
//t:指向tasklet_struct的指针

<2>tasklet_init函数

作用:动态初始化tasklet

函数原型:

文件位置路径:include/linux/interrupt.h

实际函数位置路径:kernel/softirq.c

extern void tasklet_init(struct tasklet_struct *t,
                         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;
}
EXPORT_SYMBOL(tasklet_init);
//参数
//t:指向tasklet_struct的指针
//func:tasklet绑定的函数
//data:函数执行的时候传递的函数

<3>tasklet_kill 函数

作用:删除一个tasklet

函数原型:

extern void tasklet_kill(struct tasklet_struct *t);
void tasklet_kill(struct tasklet_struct *t)
{
        if (in_interrupt())
                pr_notice("Attempt to kill tasklet from interrupt\n");

        while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
                do {
                        yield();
                } while (test_bit(TASKLET_STATE_SCHED, &t->state));
        }
        tasklet_unlock_wait(t);
        clear_bit(TASKLET_STATE_SCHED, &t->state);
}
EXPORT_SYMBOL(tasklet_kill);
//参数
//t:指向tasklet_struct的指针

注意:这个函数会等待tasklet 执行完毕,然后再将它移除。该函数可能会引起休眠,所以要禁止在中断上下文中使用。

三、使用tasklet 设计中断下文步骤

  1. 定义一个tasklet结构体
  2. 动态初始化tasklet
  3. 编写tasklet绑定的函数
  4. 在中断上文调用tasklet
  5. 卸载模块的时候删除 tasklet