http://edsionte.com/techblog/
tasklet的实现
tasklet(小任务)机制是中断处理下半部分最常用的一种方法,其使用也是非常简单的。正如在前文中你所知道的那样,一个使用tasklet的中断程
序首先会通过执行中断处理程序来快速完成上半部分的工作,接着通过调用tasklet使得下半部分的工作得以完成。可以看到,下半部分被上半部分所调用,
至于下半部分何时执行则属于内核的工作。对应到我们此刻所说的tasklet就是,在中断处理程序中,除了完成对中断的响应等工作,还要调用
tasklet,如下图示。
tasklet由tasklet_struct结构体来表示,每一个这样的结构体就表示一个tasklet。在<linux/interrupt.h>中可以看到如下的定义:
3 |
struct tasklet_struct *next; |
6 |
void (*func)(unsigned long); |
在这个结构体中,第一个成员代表链表中的下一个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 } |
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) } |
与静态创建相对的是动态创建,通过给tasklet_init函数传递一个事先定义的指针,来动态创建一个tasklet。这个函数源码如下。
1 |
470void tasklet_init(struct tasklet_struct *t, |
2 |
471 void (*func)(unsigned long), unsigned long data) |
6 |
475 atomic_set(&t->count, 0); |
相信你在阅读上面的代码是基本上没有什么难以理解的地方,不过这里还是要特别说明一下atomic_set函数:
1 |
//在arch/x86/include/asm/atomic.h中 |
2 |
35static inline void atomic_set(atomic_t *v, int i) |
首先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; |
04 |
static void mytasklet_handler(unsigned long data) |
06 |
printk("This is tasklet handler..\n"); |
09 |
static irqreturn_t myirq_handler(int irq,void* dev) |
14 |
printk("-----------%d start--------------------------\n",count+1); |
15 |
printk("The interrupt handeler is working..\n"); |
16 |
printk("The most of interrupt work will be done by following tasklet..\n"); |
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..\n"); |
从代码中可以看到,在上半部中通过调用tasklet,使得对时间要求宽松的那部分中断程序推后执行。
- 中断下半部tasklet【转】
本文转载自:http://edsionte.com/techblog/archives/1547 tasklet的实现 tasklet(小任务)机制是中断处理下半部分最常用的一种方法,其使用也是非常简 ...
- linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-100005.html linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet x ...
- Linux 中断下半部
为什么使用中断下半部? 中断执行的原则是要以最快的速度执行完,而且期间不能延时和休眠! 可是现实中,中断中可能没办法很快的处理完需要做的事,或者必须用到延时和休眠,因此引入了中断下半部. 中断中处理紧 ...
- 《Linux内核设计与实现》读书笔记(八)- 中断下半部的处理
在前一章也提到过,之所以中断会分成上下两部分,是由于中断对时限的要求非常高,需要尽快的响应硬件. 主要内容: 中断下半部处理 实现中断下半部的机制 总结中断下半部的实现 中断实现示例 1. 中断下半部 ...
- linux驱动学习笔记---实现中断下半部以及驱动编写规范(七)【转】
转自:https://blog.csdn.net/weixin_42471952/article/details/81609141 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协 ...
- linux 中断softirq tasklet
硬中断为什么不能休眠--- 中断线程以及软中断解决了什么问题---- 软中断cb函数是否允许相应本地中断,什么时候开启中断关闭中断---- 什么是软中断上下文------- 什么是tasklet 和软 ...
- 中断下半部处理之tasklet
1.tasklet概述 下半部和退后执行的工作,软中断的使用只在那些执行频率很高和连续性要求很高的情况下才需要.在大多数情况下,为了控制一个寻常的硬件设备,tasklet机制都是实现自己下半部的最佳选 ...
- 【linux kernel】 中断处理-中断下半部
欢迎转载,转载时需保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http:// ...
- 【linux kernel】 中断处理-中断下半部【转】
转自:http://www.cnblogs.com/embedded-tzp/p/4453987.html 欢迎转载,转载时需保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地 ...
随机推荐
- 【python】坑,坑,折腾一个下午python 3.5中 ImportError: No module named BeautifulSoup
将语句 from bs4 import BeautifulSoup4 改成 from bs4 import BeautifulSoup 通过 尼玛------------------------! 总 ...
- rman全备份异机恢复
一.测试环境 [oracle@localhost ~]$ uname -a Linux localhost.localdomain -.el6.x86_64 # SMP Tue May :: EDT ...
- websphere6.1安装与配置
http://www.blogjava.net/103335460/articles/220935.html 一.本人开发环境: jdk1.5.0_11 , eclipse3.2 , MyEclips ...
- PL/SQL — 显式游标
一.游标的相关概念及特性 1.定义 通过游标方式定位到结果集中某个特定的行,然后根据业务需求对该行进行相应特定的操作. 2.分类 显示游标: 用户自定义游标,用于处理select语句返回的多行数据. ...
- 软件测试 -- Bug等级划分规范
1. Blocker级别——中断缺陷 客户端程序无响应,无法执行下一步操作. 2. Critical级别――临界缺陷,包括: 功能点缺失,客户端爆页. 3. Major级别——较严重缺陷,包括: 功能 ...
- Python属性、方法和类管理系列之----__slots__属性
一句话说明 __slots__是用来限制实例的属性的,__slots__可以规定实例是否应该有__dict__属性:__slots__不能限制类的属性. 只有__slots__列表内的这些变量名可赋值 ...
- Android 绘制计时器
用小米的手机,发现其实还可以,无意间点开小米的计时器,发现界面非常好看和实用.于是自己仿照着写一个,由于技术不好,代码整体结构上可能有点乱,但主要的实现功能和掌握知识点. Android中绘制采用ca ...
- Welcome
唔.你好! 这里是 Evensgn 的笔记本. 我是 SD 省的一名高中 OIer,从初中就接触了 OI ,然而水平一直是弱弱哒. Evensgn 是我常用的 ID. 不忘初心,方能始终. E-mai ...
- BZOJ 1729: [Usaco2005 dec]Cow Patterns 牛的模式匹配
Description 约翰的N(1≤N≤100000)只奶牛中出现了K(1≤K≤25000)只爱惹麻烦的坏蛋.奶牛们按一定的顺序排队的时候,这些坏蛋总会站在一起.为了找出这些坏蛋,约翰让他的奶牛排好 ...
- [转载]C#读写配置文件(XML文件)
.xml文件格式如下 [xhtml] view plaincopy <?xml version="1.0" encoding="utf-8"?> & ...