多数情况下,为了控制一个寻常的硬件设备,tasklet机制都是实现自己下半部的最佳选择;tasklet可以动态创建,使用方便,执行起来还算快;

声明tasklet

tasklet既可以静态的创建,也可以动态的创建;如果准备静态的创建一个tasklet,可以使用下面的两个宏之一:

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

两个宏都能根据给定的名称静态的创建一个tasklet_struct结构;当该tasklet被调度以后,给定函数func会被执行,它的参数是data;前面一个宏创建的tasklet的引用计数设置为0,该tasklet处于激活状态;另一个宏引用计数为1,该tasklet处于禁止状态;

tasklet处理程序

tasklet处理程序必须符合以下定义:

 void tasklet_handler(ungigned long data)

因为靠软中断实现,所以tasklet不能睡眠;这意味着你不能再tasklet中使用信号量或者其他阻塞式的函数;由于tasklet运行时允许响应中断,所以必须做好预防工作,如果你的tasklet和中断处理程序之间共享了某些数据的话;两个相同的tasklet绝不会同时执行,这点和软中断不同,尽管两个不同的tasklet可以再两个处理器上同时执行;如果tasklet和其他的tasklet或者软中断共享了数据,就必须进行锁保护;

调度tasklet

通过调用tasklet_schedule()函数并传递给它们相应的tasklet_struct指针,该tasklet就会被调度以便执行;

 void tasklet_schedule(struct tasklet_struct *t)

在tasklet被调度以后,只要有机会它就会尽可能早的运行。在它还没有得到运行机会之前,如果有一个相同的tasklet又被调度了,那么它只会运行一次;如果这时它已经开始运行了,比如说在另外一个处理器上,那么这个新的tasklet会被调度并再次运行;作为一种优化措施,一个tasklet总在调度它的处理器上执行–这是希望能更好的利用处理器的高速缓存;

禁用启用tasklet

tasklet_disable()用来禁止某个指定的tasklet,如果该tasklet当前正在执行,这个函数会等到它执行完毕再返回;还可以调用tasklet_disable_nosync(),它也用来禁止指定的tasklet,不过它无需等待tasklet执行完毕,这么做通常不安全,因为无法估计tasklet是否仍在执行;调用tasklet_enable()可以激活一个tasklet,如果希望激活DECLARE_TASKLET_DISABLED()宏创建的tasklet,也需要调用这个函数;

 void tasklet_disable_nosync(struct tasklet_struct *t)
void tasklet_disable(struct tasklet_struct *t) void tasklet_enable(struct tasklet_struct *t)
删除挂起tasklet

可以通过调用tasklet_kill()从挂起的队列中去掉一个tasklet,该函数的参数一个指向某个tasklet的tasklet_struct指针;在处理一个经常重新调度它自身的tasklet的时候,从挂起的队列中移除已调度的tasklet很有用;这个函数首先等待tasklet执行完毕,然后再将它移除;当然,没什么方法可以阻止其他地方的代码重新调度该tasklet;由于该函数可能引起休眠,所以禁止在中断上下文中使用;

 void tasklet_kill(struct tasklet_struct *t)
ksoftirq

每个处理器都有一组辅助处理软中断(和tasklet)的内核线程;当内核中出现大量的软中断的时候,这些内核线程就会辅助处理它们;

每个处理器都有一个处理线程,名字叫做ksoftirqd/n,区别在于n,它对应着处理器的编号;在一个双处理器上就有两个这样的线程,分别叫ksoftirq/0和ksoftirq/1;为了保证只要有空闲的处理器,就会处理软中断,所以每个处理器都会分配一个这样的线程;一旦初始化,就会执行死循环处理中断;只要有待处理的中断,ksoftirq就会调度do_softirq()去处理它们;当所有中断处理完成之后,内核线程将自己设置为TASK_INTERRUPTIBLE状态,以唤起调度程序选择其他可执行线程投入运行;

Linux设备驱动程序 之 tasklet的更多相关文章

  1. linux设备驱动程序该添加哪些头文件以及驱动常用头文件介绍(转)

    原文链接:http://blog.chinaunix.net/uid-22609852-id-3506475.html 驱动常用头文件介绍 #include <linux/***.h> 是 ...

  2. 【转】linux设备驱动程序中的阻塞机制

    原文网址:http://www.cnblogs.com/geneil/archive/2011/12/04/2275272.html 阻塞与非阻塞是设备访问的两种方式.在写阻塞与非阻塞的驱动程序时,经 ...

  3. Linux设备驱动程序 第三版 读书笔记(一)

    Linux设备驱动程序 第三版 读书笔记(一) Bob Zhang 2017.08.25 编写基本的Hello World模块 #include <linux/init.h> #inclu ...

  4. Linux设备驱动程序学习之分配内存

    内核为设备驱动提供了一个统一的内存管理接口,所以模块无需涉及分段和分页等问题. 我已经在第一个scull模块中使用了 kmalloc 和 kfree 来分配和释放内存空间. kmalloc 函数内幕 ...

  5. 教你写Linux设备驱动程序:一个简短的教程

    教你写Linux设备驱动程序:一个简短的教程 http://blog.chinaunix.net/uid-20799298-id-99675.html

  6. linux设备驱动程序_hello word 模块编译各种问题集锦

    在看楼经典书籍<linux设备驱动程序>后,第一个程序就是编写一个hello word 模块. 原以为非常easy,真正弄起来,发现问题不少啊.前两天编过一次,因为没有记录,今天看的时候又 ...

  7. Linux设备驱动程序学习----1.设备驱动程序简介

    设备驱动程序简介 更多内容请参考Linux设备驱动程序学习----目录 1. 简介   Linux系统的优点是,系统内部实现细节对所有人都是公开的.Linux内核由大量复杂的代码组成,设备驱动程序可以 ...

  8. Linux设备驱动程序学习----2.内核模块与应用程序的对比

    内核模块与应用程序的对比 更多内容请参考Linux设备驱动程序学习----目录 1. 内核模块与应用程序的对比 内核模块和应用程序之间的不同之处: 大多数中小规模的应用程序是从头到尾执行单个任务,而模 ...

  9. Linux设备驱动程序学习----3.模块的编译和装载

    模块的编译和装载 更多内容请参考Linux设备驱动程序学习----目录 1. 设置测试系统 第1步,要先从kernel.org的镜像网站上获取一个主线内核,并安装到自己的系统中,因为学习驱动程序的编写 ...

随机推荐

  1. nlopt 二次优化

    /* * main.c * * Created on: Oct 9, 2018 * Author: lgh */ #include <stdio.h> #include <math. ...

  2. C# List<> Find相关接口学习

    参考 http://blog.csdn.net/daigualu/article/details/54315564 示例: List<int> test = new List<int ...

  3. GIL锁、进程池与线程池、同步异步

    GIL锁定义 GIL锁:Global Interpreter Lock  全局解释器 本质上是一把互斥锁 官方解释: 在CPython中,这个全局解释器锁,也称为GIL,是一个互斥锁,防止多个线程在同 ...

  4. 五、HashMap的使用 及其源码解析

    HashMap的底层实现原理?领接表(数组+链表)hash表数组+链表+红黑树 链表:查找慢 插入 删除快红黑树:查找快 插入 删除慢 HashMap是线程安全的吗?不是线程安全的 在什么情况下 ,是 ...

  5. SQL将同样标识的查询结果查重并用逗号拼接

    SELECT B.TaskID , LEFT(SamList, LEN(SamList) - 1) AS ResultListFROM ( SELECT TaskID , ( SELECT Sampl ...

  6. linux内核信号量

    用户态的信号量: System V 信号量 Posix 信号量 信号量是用于保护临界区的一种常用方法.它的使用和自旋锁类似.相同的是,只有得到信号量的进程才能执行临界区代码:不同的是,当获取不到信号量 ...

  7. Java基础加强-读取配置文件和内省

    Java读取配置文件 1.采用ServletContext读取,读取配置文件的realpath,然后通过文件流读取出来. String path = "/WEB-INF/jdbc_conne ...

  8. 使用.bat 批量将部分文件迁移到新的路径下

    1.建一个11.bat ,里面写  :   dir  /b /s  >1111.txt 保存后运行 即将所有的文件路径保存到1111.txt中 2.可以将获取的路径复制到execl中,找到自己需 ...

  9. CentOS 7 配置VNCServer

    因为一直在用xmanager ,所以CentOS 7 上没过VNCSserver了,最近安装Oracle19C ,xmanager 总是卡死,所以配置VNC. 发现仅仅yum install -y t ...

  10. Computer Vision_33_SIFT:Speeded-Up Robust Features (SURF)——2006

    此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...