Chinaunix首页 | 论坛 | 博客
  • 博客访问: 30980
  • 博文数量: 5
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 68
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-21 15:05
文章分类
文章存档

2016年(1)

2015年(4)

我的朋友

分类: LINUX

2015-12-21 10:37:19

tasklet是基于软中断实现的一种下半部机制。tasklet和软中断在本质上很相似,行为表现也很相近。

tasklet的实现:
tasklet有两类软中断代表:HI_SOFTIRQ和TASKLET_SOFTIRQ,这两者之间唯一的实际区别在于,HI_SOFTIRQ类型的软中断先于TASKLET_SOFTIRQ类型的软中断执行。    

tasklet结构体,中定义:
    struct tasklet_struct {
        struct tasklet_struct *next;/*链表中的下一个tasklet。正是因为tasklet使用链表形式实现的,所以使得tasklet可以被动态的创建多个*/
        unsigned long state;/*tasklet的状态。三种取值:0、TASKLET_STATE_SCHED和TASKLET_STATE_RUN(只用于在多CPU 情况下进行优化使用,因为同种类型的tasklet处理程序在同一时间只能运行一个),单CPU上tasklet状态要么是0(没在运行),要么是 TASKLET_SATE_SCHED(正在运行)*/
        atomic_t count;/*引用计数器,用于标记tasklet是否为激活状态,只有当count为0时才会被激活运行*/
        void (*func)(unsigned long);/*tasklet的处理程序*/
        unsigned long data;/*传递给tasklet处理程序的参数*/
    };

tasklet的调度:
可以类比于softirq的触发,
    1)softirq通过raise_softirq或raise_softirq_irqoff函数触发软中断,而tasklet通过 tasklet_schedule(HI_SOFTIRQ也类似,以下均已TASKLET_SOFTIRQ为例)进行触发tasklet,当然必须首先得 触发TASKLET_SOFTIRQ软中断。
static inline void tasklet_schedule(struct tasklet_struct *t)
{
        if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))//在同一时刻只能有一个tasklet在执行
                __tasklet_schedule(t);
}
void fastcall __tasklet_schedule(struct tasklet_struct *t)
{
        unsigned long flags;
        local_irq_save(flags);
        t->next = __get_cpu_var(tasklet_vec).list; //触发tasklet,其实就是把tasklet加到tasklet_vec链表中去
        __get_cpu_var(tasklet_vec).list = t;
        raise_softirq_irqoff(TASKLET_SOFTIRQ); //触发软中断
        local_irq_restore(flags);
}
    2)softirq在执行时(do_softirq),流程为:关中断->获取待处理的softirq位图-->逐个执行softirq的处 理程序;tasklet也一样,由于tasklet是基于软中断的,所以也得通过do_softirq执行,当遍历到TASKLET_SOFTIRQ时, 执行tasklet_action函数。在tasklet_action函数中去处理待处理的tasklet。通过分析tasklet_action函 数,可以看出,其实现思路与do_softirq实现思路很相似:
static void tasklet_action(struct softirq_action *a)
{
        struct tasklet_struct *list;
        local_irq_disable(); //关中断
        list = __get_cpu_var(tasklet_vec).list; //获取待处理的tasklet链表
        __get_cpu_var(tasklet_vec).list = NULL; //将tasklet链表清空
        local_irq_enable(); //打开中断,意味着tasklet在执行的时候是可能被中断打断的。
        while (list) {//遍历链表,执行待处理的tasklet
                struct tasklet_struct *t = list;
                list = list->next;
                if (tasklet_trylock(t)) {
                        if (!atomic_read(&t->count)) {
                                if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
                                        BUG();
                                t->func(t->data);
                                tasklet_unlock(t);
                                continue;
                        }
                        tasklet_unlock(t);
                }
                local_irq_disable();
                t->next = __get_cpu_var(tasklet_vec).list;
                __get_cpu_var(tasklet_vec).list = t;
                __raise_softirq_irqoff(TASKLET_SOFTIRQ);
                local_irq_enable();
        }
}
阅读(2159) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~