zoukankan      html  css  js  c++  java
  • [linux内核]中断下半部分——tasklet

    1,Tasklet的概念

    tasklet是利用软中断实现的一种下半部机制,tasklet由两类软中断的代表,HI_SOFTIRQ和TASKLET_SOFTIRQ,这两个的区别是HI_SOFTIRQ类型的软中断先于TASKLET_SOFTIRQ类型的软中断先执行。

    tasklet由tasklet_struct结构表示,每个结构单独代表一个tasklet,在interrupt.h中定义。

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. 420 struct tasklet_struct  
    2. 421 {  
    3. 422         struct tasklet_struct *next;  
    4. 423         unsigned long state;  //state成员的值在0,TASKLET_STATE_SCHED和TASKLET_STATE_RUN之间取值,TASKLET_STATE_SCHED表明该tasklet已经被调度正准备投入运行。  
    5. 424         atomic_t count;  //tasklet的引用计数,如果它不为0则tasklet被禁止,  
    6. 425         void (*func)(unsigned long);  
    7. 426         unsigned long data;  
    8. 427 };  


    tasklet由tasklet_schedule()函数进行调度,

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <span style="font-weight: bold; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">2,Tasklet机制</span>  

    1)声明自己的Tasklet

    静态创建:

    既可以使用<linux/interrupt.h>中定义的两个宏中的一个DECLARE_TASKLET或DECLARE_TASKLET_DISABLED来静态创建tasklet,前者把创建的tasklet的引用计数器设置为0,该tasklet处于激活状态。另一个把引入计数器设为1,所以该tasklet处于禁止状态。还可以使用tasklet_init()动态创建一个tasklet。

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. 429 #define DECLARE_TASKLET(name, func, data)   
    2. 430 struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }  

    动态创建:

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. struct msdc_host{  
    2.     struct tasklet_struct card_tasklet;  
    3. };  
    4. struct msdc_host *host;  
    5. tasklet_init(&host->card_tasklet,msdc_tasklet_card,unsigned long arg);//msdc_tasklet_card是tasklet处理函数  
    6. tasklet_hi_schedule(&host->card_tasklet);  
    7.   
    8. 470 void tasklet_init(struct tasklet_struct *t,  
    9. 471                   void (*func)(unsigned long), unsigned long data)  
    10. 472 {  
    11. 473         t->next = NULL;  
    12. 474         t->state = 0;  
    13. 475         atomic_set(&t->count, 0);  
    14. 476         t->func = func;  
    15. 477         t->data = data;  
    16. 478 }  

    2)编写自己的tasklet处理程序

    tasklet处理程序必须符合规定的函数类型:void tasklet_handler(unsigned long data)。因为是靠软中断实现,所以tasklet不能睡眠。这意味着你不能在tasklet中使用信号量或其他什么阻塞式函数。如果你的tasklet和其他的tasklet或软中断共享了数据,你必须进行适当的锁保护。

    3)调度自己的tasklet

    通过调用tasklet_schedule()函数来调度。在tasklet被调度以后在其还没有得到运行机会之前,如果一个相同的tasklet又被调度了,那么它仍只会运行一次。而如果这时它已经开始运行了,那么这个新的tasklet会被重新调度并再次运行。作为一种优化措施,一个tasklet总在调度它的处理器上执行-这是希望更好地利用处理器的高速缓存。可以调用tasklet_disable()函数来禁止某个指定的tasklet,也可以调用tasklet_enable()函数激活一个tasklet。还可以调用tasklet_kill()函数从挂起的队列中去掉一个tasklet。

    3,ksoftirqd

    每个处理器都有一个这样的线程,所有的线程名字都叫ksoftirqd/n,n对应于处理器的编号,这些线程是在最低的优先级上运行(nice值是19),这样好处是它们和其它重要的认为抢夺资源,在空闲的系统上,这个方案也表现良好。

    4,工作队列和tasklet的区别~

    工作队列运行在进程上下文中,可以中断,如果你的中断下半部分需要睡眠,那么应该使用工作队列的机制。

  • 相关阅读:
    POJ 2209
    POJ 2196
    POJ 2215
    POJ 2192
    POJ 2195
    POJ 2181
    POJ 2182
    POJ 2159
    POJ 2153
    字符设备驱动 —— 字符设备驱动框架
  • 原文地址:https://www.cnblogs.com/zhiliao112/p/4232141.html
Copyright © 2011-2022 走看看