一个使用tasklet的中断程序首先会通过执行中断处理程序来快速完成上半部分的工作,接着通过调度tasklet使得下半部分的工作得以完成,但是下半部分何时执行属于内核的工作。

由于tasklet依靠软中断实现,所以tasklet不能休眠。这就意味着不能在tasklet中使用信号量或其他任何可能引起阻塞的函数。两个相同的tasklet绝不会同时执行。这点是和软中断的一个重要的区别。尽管两个不同的tasklet可以在两个处理器上同时执行,但只要不同的tasklet不共享数据,就不会有任何问题。当然,如果要共享数据,仍然需要使用本地锁保护临界区数据。

本文档描述基于3.14.77内核。

1. 定义

tasklet定义在linux/interrupt.h中,实现在kernel/softirq.c中。

struct tasklet_struct {
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long);
unsigned long data; // 给tasklet处理函数传递的参数
};

tasklet_struct.state可以设置成0,也可以设置成两个枚举值(TASKLET_STATE_SCHED和TASKLET_STATE_RUN),除此之外,tasklet_struct.state不能设置成其他的值。

enum
{
TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */
TASKLET_STATE_RUN /* Tasklet is running (SMP only) */
};

tasklet_struct.count是tasklet的引用计数器,如果count不为0,表示tasklet被禁用,不允许执行。只有当count为0时,tasklet才会被激活,并且只有tasklet被设置为挂起时,该tasklet才能被执行(下一次调用do_softirq函数时会执行所有挂起的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 } void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data);

由于tasklet_init函数本身不会创建tasklet_struct结构体,因此,在调用tasklet_init函数之前,需要使用kmalloc或其他类似的内核空间分配函数为tasklet_struct结构体分配内存空间(动态创建tasklet_struct结构体)。

调度

tasklet_schedule(&mytasklet);  //调用底半部,注意,这不是立即调用,是调度,意味着tasklet底半部会在顶半部执行完成后才会执行。

在_tasklet_schedule函数中调用raise_softirq_irqoff函数挂起了TASKLET_SOFTIRQ中断。这就意味着一旦do_softirq函数在某个时刻被调用,系统就会扫描软中断向量表(softirq_vec),这时发现TASKLET_SOFTIRQ软中断被挂起,就会立刻执行与TASKLET_SOFTIRQ软中断对应的处理程序。在TASKLET_SOFTIRQ软中断处理程序中会扫描tasklet向量表(tasklet_vec)。

销毁

一般会在Linux驱动的exit函数中使用tasklet_kill函数(kernel/softirq.c)销毁当前的tasklet,实际上就是将tasklet_struct.state设为0。

extern void tasklet_kill(struct tasklet_struct *t);
extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);

2. 应用

static struct tasklet_struct my_tasklet;   

static void tasklet_handler (unsigned long data)
{
printk(KERN_ALERT "tasklet_handler is running.\n");
} tasklet_init(&my_tasklet, tasklet_handler, ); // 初始化tasklet
tasklet_schedule(&my_tasklet); // 调度tasklet处理程序 tasklet_kill(&my_tasklet);

3. 小结

由于软中断是Linux系统全局的,整个Linux系统最多也只能有10个不同类型的软中断。而且如果不修改Linux内核源代码,这个最大中断数是不会变的,就算修改了内核源代码,最大也只能有32个软中断。为了可以处理更多的底半部,系统定义了两个特殊的软中断(HI_SOFTIRQ和TASKLET_SOFTIRQ),通过这两个软中断的处理函数可以执行两个tasklet向量(tasklet_vec和tasklet_hi_vec)中的tasklet处理程序。因此tasklet处理程序的执行效率要比软中断处理程序的执行效率低一些(也低不了太多)。这是因为tasklet处理程序需要先执行软中断处理程序,然后才能扫描tasklet向量,比软中断处理程序多了一步。

参考:

1. tasklet_workqueue

2. linux内核对中断的处理方式

3. tasklet

小任务tasklet应用的更多相关文章

  1. Linux软中断、tasklet和工作队列

    Linux内核中的软中断.tasklet和工作队列详解 引言 软中断.tasklet和工作队列并不是Linux内核中一直存在的机制,而是由更早版本的内核中的“下半部”(bottom half)演变而来 ...

  2. linux中的tasklet机制【转】

    转自:http://blog.csdn.net/yasin_lee/article/details/12999099 转自: http://www.kerneltravel.net/?p=143 中断 ...

  3. Linux tasklet 和workqueue学习

    中断服务程序一般都是在中断请求关闭的条件下执行的,以避免嵌套而使中断控制复杂化.但是,中断是一个随机事件,它随时会到来,如果关中断的时间太长,CPU就不能及时响应其他的中断请求,从而造成中断的丢失.因 ...

  4. linux 中断softirq tasklet

    硬中断为什么不能休眠--- 中断线程以及软中断解决了什么问题---- 软中断cb函数是否允许相应本地中断,什么时候开启中断关闭中断---- 什么是软中断上下文------- 什么是tasklet 和软 ...

  5. linux中断编程

    本文档只介绍中断编程所需的函数及应用,中断完整处理流程应参考文档<linux中断处理流程>,可参考文档<linux内核对中断的处理方式>对中断初步了解. 本文档基于3.14内核 ...

  6. Linux 中断下半部

    为什么使用中断下半部? 中断执行的原则是要以最快的速度执行完,而且期间不能延时和休眠! 可是现实中,中断中可能没办法很快的处理完需要做的事,或者必须用到延时和休眠,因此引入了中断下半部. 中断中处理紧 ...

  7. 内核源码分析之tasklet(基于3.16-rc4)

    tasklet是在HI_SOFTIRQ和TASKLET_SOFTIRQ两个软中断的基础上实现的(它们是在同一个源文件中实现,由此可见它们的关系密切程度),它的数据结构和软中断比较相似,这篇博文将分析t ...

  8. 中断下半部-tasklet

    http://edsionte.com/techblog/ tasklet的实现 tasklet(小任务)机制是中断处理下半部分最常用的一种方法,其使用也是非常简单的.正如在前文中你所知道的那样,一个 ...

  9. tasklet和workqueue的选择

    linux内核设计与实现page127中有个比較,内容比較多.概括一下就是1. tasklet不能休眠, 2. 不须要休眠tasklet效率更高 3.有休眠仅仅能workqueue (1)假设不须要休 ...

随机推荐

  1. HDUOJ-----(1329)Calling Extraterrestrial Intelligence Again

    Calling Extraterrestrial Intelligence Again Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: ...

  2. C++知识整理(在此感谢大牛的整理)

    这篇文章主要讲解如何在C++中使用cin/cout进行高级的格式化输出操作,包括数字的各种计数法(精度)输出,左或右对齐,大小写等等.通过本文,您可以完全脱离scanf/printf,仅使用cin/c ...

  3. 【js与jquery】jquery循环滚动新闻

    2.html代码: <h3>最新动态</h3> <div class="scrollNews" > <ul> <li>& ...

  4. Hadoop分布式文件系统:架构和设计

    原文地址:http://hadoop.apache.org/docs/r1.0.4/cn/hdfs_design.html 引言 前提和设计目标 硬件错误 流式数据访问 大规模数据集 简单的一致性模型 ...

  5. setContentView(R.layout.activity_main)无法正常引用

    今天在写Android代码的过程中,编译器一直报错,错误出在这一行代码: setContentView(R.layout.activity_main) 提示信息是: activity_main can ...

  6. CentOS7 安装配置DNS服务器

    一.安装 yum install bind 二.配置 1. /etc/named.conf // // named.conf // // Provided by Red Hat bind packag ...

  7. Note for video Machine Learning and Data Mining——training vs Testing

    Here is the note for lecture five. There will be several points  1. Training and Testing  Both of th ...

  8. js 数据结构-栈与队列

    /*[客栈的盘子/月井里的货物,后进先出]栈顶:最先入口/出口的位置栈底:最慢最晚出栈的位置*/ function Stack() { var item = []; //推(将货物推入月井) this ...

  9. php教程之php空白页的原因及解决方法

    php中出现空白页的原因及解决方法汇总. 很多程序员在进行php开发的时候都遇到过出现空白页的请,综合分析来说,在php编程中出现空白页面可能是由以下几个原因造成的: 1.逻辑错误逻辑错误是最难排除的 ...

  10. Animator根运动清除刚体速率问题测试

    在根运动打开时,施加AddForce,速率在后面几帧被清0了: 没有打开根运动AddForce的情况: unity论坛看了下,似乎有人遇到这个问题,而且无解.只能受力状态下关闭根运动 Q:Im wor ...