• 中断下半部-tasklet


    http://edsionte.com/techblog/

    tasklet的实现


    tasklet(小任务)机制是中断处理下半部分最常用的一种方法,其使用也是非常简单的。正如在前文中你所知道的那样,一个使用tasklet的中断程 序首先会通过执行中断处理程序来快速完成上半部分的工作,接着通过调用tasklet使得下半部分的工作得以完成。可以看到,下半部分被上半部分所调用, 至于下半部分何时执行则属于内核的工作。对应到我们此刻所说的tasklet就是,在中断处理程序中,除了完成对中断的响应等工作,还要调用 tasklet,如下图示。

    tasklet由tasklet_struct结构体来表示,每一个这样的结构体就表示一个tasklet。在<linux/interrupt.h>中可以看到如下的定义:

    1 tasklet_struct
    2 {
    3     struct tasklet_struct *next;
    4     unsigned long state;
    5     atomic_t count;
    6     void (*func)(unsigned long);
    7     unsigned long data;
    8 };

    在这个结构体中,第一个成员代表链表中的下一个tasklet。第二个变量代表此刻tasklet的状态,一般为 TASKLET_STATE_SCHED,表示此tasklet已被调度且正准备运行;此变量还可取TASKLET_STATE_RUN,表示正在运行, 但只用在多处理器的情况下。count成员是一个引用计数器,只有当其值为0时候,tasklet才会被激活;否则被禁止,不能被执行。而接下来的 func变量很明显是一个函数指针,它指向tasklet处理函数,这个处理函数的唯一参数为data。



    使用tasklet


    在使用tasklet前,必须首先创建一个tasklet_struct类型的变量。通常有两种方法:静态创建和动态创建。这样官方的说法仍然使我们不能理解这两种创建到底是怎么一回事。不够透过源码来分析倒是可以搞明白。

    在<linux/interrupt.h>中的两个宏:

    1 464#define DECLARE_TASKLET(name, func, data)
    2 465struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
    3 466
    4 467#define DECLARE_TASKLET_DISABLED(name, func, data)
    5 468struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }

    就是我们进行静态创建tasklet的两种方法。通过第一个宏创建的tasklet处于激活状态,再通过调度函数被挂起尽而被内核执行;而通过第二 个宏创建的tasklet处于禁止状态。从两个宏的定义可以看到,所谓的静态创建就是直接定义个一个名为name的tasklet_struct类型的变 量,并将宏中各个参数相应的赋值给这个name变量的各个成员。注意,两个宏在功能上差异就在于对name变量count成员的赋值上,具体原因在第一部 分已经说明。也许你对ATOMIC_INIT这样的初始化方式感到疑惑,那么看完定义后,你就会一目了然:

    1 //在arch/x86/include/asm/atomic.h中
    2 15#define ATOMIC_INIT(i)  { (i) }
    3 //在linux/types.h中
    4 190typedef struct {
    5 191        int counter;
    6 192} atomic_t;

    与静态创建相对的是动态创建,通过给tasklet_init函数传递一个事先定义的指针,来动态创建一个tasklet。这个函数源码如下。

    1 470void tasklet_init(struct tasklet_struct *t,
    2 471                  void (*func)(unsigned long), unsigned long data)
    3 472{
    4 473        t->next = NULL;
    5 474        t->state = 0;
    6 475        atomic_set(&t->count, 0);
    7 476        t->func = func;
    8 477        t->data = data;
    9 478}

    相信你在阅读上面的代码是基本上没有什么难以理解的地方,不过这里还是要特别说明一下atomic_set函数:

    1 //在arch/x86/include/asm/atomic.h中
    2 35static inline void atomic_set(atomic_t *v, int i)
    3 36{
    4 37        v->counter = i;
    5 38}

    首先tasklet_init当中,将&t->count传递给了此函数。也就是说将atomic_t类型的成员count的地址传 递给了atomic_set函数。而我们在此函数中却要为count变量中的成员counter赋值。如果说我们当前要使用i,那么应该是如下的引用方 法:t-》count.i。明白了吗?

    ok,通过上述两种方法就可以创建一个tasklet了。同时,你应该注意到不管是上述那种创建方式都有func参数。透过上述分析的源码,我们可以看到func参数是一个函数指针,它指向的是这样的一个函数:

    1 void tasklet_handler(unsigned long data);

    如同上半部分的中断处理程序一样,这个函数需要我们自己来实现。

    创建好之后,我们还要通过如下的方法对tasklet进行调度:

    1 tasklet_schedule(&my_tasklet)

    通过此函数的调用,我们的tasklet就会被挂起,等待机会被执行



    一个举例


    在此只分析上下两部分的调用关系,完整代码在这里查看。

    01 //define a argument of tasklet struct
    02 static struct tasklet_struct mytasklet;
    03  
    04 static void mytasklet_handler(unsigned long data)
    05 {
    06     printk("This is tasklet handler.. ");
    07 }
    08  
    09 static irqreturn_t myirq_handler(int irq,void* dev)
    10 {
    11     static int count=0;
    12     if(count<10)
    13     {
    14         printk("-----------%d start-------------------------- ",count+1);
    15                 printk("The interrupt handeler is working.. ");
    16                 printk("The most of interrupt work will be done by following tasklet.. ");
    17                 tasklet_init(&mytasklet,mytasklet_handler,0);
    18             tasklet_schedule(&mytasklet);
    19                 printk("The top half has been done and bottom half will be processed.. ");
    20     }
    21     count++;
    22         return IRQ_HANDLED;
    23 }

    从代码中可以看到,在上半部中通过调用tasklet,使得对时间要求宽松的那部分中断程序推后执行。

  • 相关阅读:
    P2480 [SDOI2010]古代猪文(CRT+Lucas+费马小定理)
    P2473 [SCOI2008]奖励关(状压+期望dp)
    P2485 [SDOI2011]计算器(快速幂+扩欧+bsgs)
    板子
    https://lydsy.download/archive/
    [SDOI2010]地精部落(dp)
    P2446 [SDOI2010]大陆争霸(有限制的最短路)
    博客园在页面内设置超链接
    Matlab 绘制双纵轴图
    Matlab画图线型、符号及颜色汇总
  • 原文地址:https://www.cnblogs.com/0822vaj/p/4104890.html
Copyright © 2020-2023  润新知