[linux中断]中断下半部分——tasklet

来源:互联网 发布:sql server 2014 安装 编辑:程序博客网 时间:2024/04/29 12:09

1,Tasklet的概念

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

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

420 struct tasklet_struct421 {422         struct tasklet_struct *next;423         unsigned long state;  //state成员的值在0,TASKLET_STATE_SCHED和TASKLET_STATE_RUN之间取值,TASKLET_STATE_SCHED表明该tasklet已经被调度正准备投入运行。424         atomic_t count;  //tasklet的引用计数,如果它不为0则tasklet被禁止,425         void (*func)(unsigned long);426         unsigned long data;427 };

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

<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。

429 #define DECLARE_TASKLET(name, func, data) \430 struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }

动态创建:

struct msdc_host{struct tasklet_struct card_tasklet;};struct msdc_host *host;tasklet_init(&host->card_tasklet,msdc_tasklet_card,unsigned long arg);//msdc_tasklet_card是tasklet处理函数tasklet_hi_schedule(&host->card_tasklet);470 void tasklet_init(struct tasklet_struct *t,471                   void (*func)(unsigned long), unsigned long data)472 {473         t->next = NULL;474         t->state = 0;475         atomic_set(&t->count, 0);476         t->func = func;477         t->data = data;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的区别~

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

0 0
原创粉丝点击