Chinaunix首页 | 论坛 | 博客
  • 博客访问: 716096
  • 博文数量: 67
  • 博客积分: 994
  • 博客等级: 准尉
  • 技术积分: 1749
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-03 14:10
文章分类
文章存档

2014年(11)

2013年(14)

2012年(14)

2011年(28)

分类: LINUX

2011-11-12 17:57:31

首先我们先要了解为什么要使用下半部机制:前面已经说过中断处理程序既要保持快速执行,也就是尽力缩短中断处理程序的执行,还要与其他处理程序异步执行,要保持高效行就要把一些工作推后执行,具体怎么个推后,要理解不是马上执行,而是載中断恢复后执行就OK了。

下半部的实现机制在2.6之前提供了小任务和任务队列来实现,2.6之后包括软中断、tasklet和工作队列。其中tasklet是通过软中断来实现的。下面我们就来分别认识下三种实现机制:

软中断:软中断是載编译期间静态分配的。tasklet是软中断的一个特例。软中断具有可扩展性,如果不需要扩展就成了tasklet

这这里提到软中断就要和硬中断作一区别:

硬中断是外设对CPU的中断,而软中断是硬中断服务程序对内核的中断。

软中断由softirq_action结构表示,具体原型如下:

struct softirq_action

432 {

433 void (*action)(struct softirq_action *);

434 };

435

软中断的处理程序函数原型如下:

void softirq_handler(struct softirq_action *)

当内核运行一个软中断处理程序的时候,它就会执行这个action函数,其唯一的参数为指向相应的softirq_action 的结构体。

软中断的注册通过void (int , void (*)(struct *))

相应的两个参数:软中断的索引号和处理函数。


tasklet是利用软件中断实现的一种下半部机制,相对与其他,它的接口更为简单,且经常被使用。tasklet又叫小任务。

Tasklet结构体

tasklettasklet_struct结构体表示,具体定义如下:

struct tasklet_struct

497 {

498 struct tasklet_struct *next; //指向链表中的下一个结构

499 unsigned long state; //小任务的状态

500 atomic_t count; //引用计数器

501 void (*func)(unsigned long); //小任务的处理函数

502 unsigned long data; //传递给小任务处理函数的参数

503 };

小任务既可以静态的创建也可以动态的创建,静态的创建一个小任务,则任选下面两个宏之一即可:

#define DECLARE_TASKLET(name, func, data) \

506 struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }


#define DECLARE_TASKLET_DISABLED(name, func, data) \

509 struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }

大家估计看出了两个宏的区别,第一个的引用计数器设置为0,表示小任务处于激活状态,而另一个置1,则说明小任务处于禁止状态。具体创建如下:

struct tasklet_struct my_tasklet={ NULL, 0, ATOMIC_INIT(0), tasklet_handler, dev };

上面提到了tasklet_handler,这也就是自己编写的一个小任务处理程序,函数类型如下:void tasklet_handler,unsigned long data

注意:小任务不能睡眠,所以不能載小任务中使用信号量或者其他产生阻塞的函数,但是小任务可以相应中断。

小任务的调度:

小任务被调度之后,已有机会它就会运行。调度函数如下:

static inline void tasklet_schedule(struct tasklet_struct *t)

543 {

544 if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))

545 __tasklet_schedule(t);

}

tasklet_schedule主要是通过 __tasklet_schedule来实现。这也体现了代码复用的思想。

调度完成之后小任务有时候还需要被激活,这可以通过 tasklet_enable函数实现。


阅读(1921) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~