《linux内核设计与实现2》章节中p80
tasklet结构体
-
linux-2.6.35 src/include/linux/interrupt.h
-
-
450 struct tasklet_struct
-
451 {
-
452 struct tasklet_struct *next;//链表中的下一个tasklet
-
453 unsigned long state; //tasklet的状态
-
454 atomic_t count; // 引用计数器
-
455 void (*func)(unsigned long);//tasklet处理函数
-
456 unsigned long data;//给tasklet处理函数的参数
-
457 };
state参数:0、TASKLET_STATE_SCHED、TASKLET_STATE_RUN之间一个
在src/linux/interrupt.h 定义了上述
-
466 enum
-
467 {
-
468 TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution tasklet已被调度,正准备投入运行
-
469 TASKLET_STATE_RUN /* Tasklet is running (SMP only) */tasklet正在运行
-
470 };
-
471
count参数:是tasklet的引用参数。如果它不为0,则tasklet被禁止,不允许执行;只有当它为0时,tasklet才被激活,并且在被设置为挂起状态时,该tasklet才能够执行。 N_NONBLOCK 非阻塞
大多数情况下,为了控制一个寻常的硬件设备,tasklet机制都是实现你自己的下半部的最佳选择。
1. 声明自己的tasklet
我们可以静态或动态分别创建它。
静态创建:
DECLARE_TASKLET(name,func,data);//引用计数器count=0,激活状态
DECLARE_TASKLET_DISABLE(name,func,data);//引用计数器count=1,禁止状态
这里的data是unsigned long类型,传入 void func(unsigned long p)函数中
这里声明
DECLARE_TASKLET(mytasklet,myhandler,dev)等同于
struct tasklet_struct mytasklet={NULL,0,ATOMIC_INIT(0),myhandler,dev};
动态创建
src/kernel/softirq.c
-
void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long),unisgned long data);
初始化 tasklet_struct 结构体,将引用计数器count=0,和状态state=0。
struct tasklet_struct my_tasklet;
tasklet_init(&my_tasklet,myfunc,data);//动态创建
2. 编写自己的tasklet处理程序
void tasklet_handler(unsigned long data);
y因为是靠软中断实现,所以在tasklet不能睡眠。那么不能再tasklet中使用 信号量或者其他睡眠阻塞式的函数。
3. 调度自己的tasklet
tasklet_schedule(&my_tasklet);//把my_tasklet标记为挂起
4.开启、关闭指定的tasklet
tasklet_disable(&my_tasklet);
.......
tasklet_enable(&my_tasklet);
========================================================================
增加的内容:
-
static struct tasklet_struct mytasklet;
-
...
-
-
////tasklet底半部机制 处理函数
-
static void mytasklet_handler(unsigned long data);
-
...
-
-
static irqreturn_t myirq_handler(int irq, void *dev)
-
{
-
static int count = 0;
-
if(count<10)
-
{
-
printk("<0>--%d start--\n",count+1);
-
tasklet_init(&mytasklet,mytasklet_handler,0);////动态申请 tasklet
-
tasklet_schedule(&mytasklet);
-
printk("<0>the top hafl has beed done and bottme will be process..\n");
-
}
-
else
-
{
-
printk("count=%d\n",count);
-
}
-
count++;
-
-
return IRQ_HANDLED;
-
}
-
-
static void mytasklet_handler(unsigned long data)
-
{
-
printk("<0>this is tasklet handler..\n");
-
}
-
使用方法:
-
root@ywx:/home/ywx/desktop/module/edi/interrupt/interrupt_tasklet# cat /proc/interrupts | grep ywx //查看没有 ywx这个中断
-
root@ywx:/home/ywx/desktop/module/edi/interrupt/interrupt_tasklet# insmod ./interrupt.ko irq=1 devname=ywxdevname
-
root@ywx:/home/ywx/desktop/module/edi/interrupt/interrupt_tasklet# cat /proc/interrupts | grep ywx
-
1: 33785 IO-APIC-edge i8042, ywxdevname 中断号名称
-
root@ywx:/home/ywx/desktop/module/edi/interrupt/interrupt_tasklet# dmesg | tail -100 | more
-
[31967.389901] Module is working...
-
[31967.389987] ywxdevname request IRQ:1 success..
-
[31967.467587] --1 start--
-
[31967.467692] the top hafl has beed done and bottme will be process..
-
[31967.467759] this is tasklet handler..
-
[31968.315207] --2 start--
-
[31968.315237] the top hafl has beed done and bottme will be process..
-
[31968.315247] this is tasklet handler..
-
。。。。
-
[31970.429523] --10 start--
-
[31970.429542] the top hafl has beed done and bottme will be process..
-
[31970.429552] this is tasklet handler.. 当操作10次键盘中断后,只显示中断次数了
-
[31970.514558] count=10
-
[31971.157066] count=11
-
[31971.157987] count=12
-
[31971.264544] count=13
=============================================================
资料:
1.edsionte's Linuxworld|新手区 中断下半部-tasklet
阅读(1739) | 评论(0) | 转发(0) |