Kernel tasklet
2019独角兽企业重金招聘Python工程师标准>>>
内核 tasklet 机制是在软中断的基础上实现的。我们知道软中断有如下两点,导致比较难用:
(1)软中断在内核中静态注册。如果要增加新的软中断,必须修改内核代码,重新编译内核镜像。
(2)SMP系统中,软中断action被所有CPU共享(即,同一个软中断同时可以在多个CPU上运行),需要用户自己保证软中断处理函数的可重入性。
tasklet 设计目标就是解决软中断如上两点不足之处,使得中断处理简单易用。针对第一点,tasklet设计了链表结构,提供 tasklet_schedule() 和 tasklet_hi_schedule() 等接口供用户动态注册 tasklet 处理函数;针对第二点,tasklet 设计了per-cpu变量(即,每个CPU都维护自己的一份 tasklet链表结构),从而避免了同一个 tasklet 被多个CPU共享,使得 tasklet 的处理函数不必是可重入的。
tasklet 占用两种软中断类型,一种是 HI_SOFTIRQ,代表高优先级的tasklet;另外一种是 TASKLET_SOFTIRQ,代表低优先级的 tasklet,两种类型的 tasklet 在实现原理上一样,以下仅以 TASKLET_SOFTIRQ 为例分析其工作原理。
tasklet 数据关系如下图所示:
1,tasklet及链表结构:
struct tasklet_struct
{
struct tasklet_struct *next; // 链表指针
unsigned long state; // 状态:是否运行,是否被调度
atomic_t count; // 引用计数
void (*func)(unsigned long); // tasklet处理函数
unsigned long data; // tasklet处理数据
};
struct tasklet_head {
struct tasklet_struct *head; // 指向tasklet链表头
struct tasklet_struct **tail; // 指向tasklet链表尾
};
2,tasklet软中断注册:
由于tasklet是基于软中断实现的,那么tasklet首先得在软中断上注册一个软中断处理函数 tasklet_action(),然后,被软中断调度运行的 tasklet_action 在per-cpu变量 tasklet_vec中找到当前CPU对应的 tasklet_head 链表,一次处理完该链表上所有的 tasklet_struct:
void __init softirq_init(void)
{
int cpu;
for_each_possible_cpu(cpu) {
per_cpu(tasklet_vec, cpu).tail =
&per_cpu(tasklet_vec, cpu).head;
per_cpu(tasklet_hi_vec, cpu).tail =
&per_cpu(tasklet_hi_vec, cpu).head;
}
open_softirq(TASKLET_SOFTIRQ, tasklet_action); // 注册低优先级 tasklet 处理函数 tasklet_action
open_softirq(HI_SOFTIRQ, tasklet_hi_action); // 注册高优先级 tasklet 处理函数 tasklet_hi_action
}
3,调度运行每个 tasklet_struct:
static void tasklet_action(struct softirq_action *a)
{
struct tasklet_struct *list;
local_irq_disable(); // 关中断操作链表
list = __this_cpu_read(tasklet_vec.head); // 从 tasklet_vec 中一次性获取当前CPU上的所有 tasklet_struct
__this_cpu_write(tasklet_vec.head, NULL);
__this_cpu_write(tasklet_vec.tail, this_cpu_ptr(&tasklet_vec.head));
local_irq_enable(); // 开中断
while (list) { // 循环处理链表中所有 tasklet_struct
struct tasklet_struct *t = list;
list = list->next;
if (tasklet_trylock(t)) {
if (!atomic_read(&t->count)) {
if (!test_and_clear_bit(TASKLET_STATE_SCHED,
&t->state))
BUG();
t->func(t->data); // 调度 tasklet 处理函数
tasklet_unlock(t);
continue;
}
tasklet_unlock(t);
}
local_irq_disable();
t->next = NULL;
*__this_cpu_read(tasklet_vec.tail) = t;
__this_cpu_write(tasklet_vec.tail, &(t->next));
__raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_enable();
}
}
4,tasklet的用户初始化和动态注册:
(1)用户初始化 tasklet:
void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data)
{
t->next = NULL;
t->state = 0;
atomic_set(&t->count, 0);
t->func = func;
t->data = data;
}
(2)用户注册 tasklet:
static inline void tasklet_schedule(struct tasklet_struct *t)
{
if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
__tasklet_schedule(t);
}
void __tasklet_schedule(struct tasklet_struct *t)
{
unsigned long flags;
local_irq_save(flags);
t->next = NULL;
*__this_cpu_read(tasklet_vec.tail) = t;
__this_cpu_write(tasklet_vec.tail, &(t->next));
raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_restore(flags);
}
tasklet_schedule() 将用户定义的 tasklet_struct 加入当前CPU的 tasklet 链表中,等待 tasklet_action()在适当的时候调度执行。
注意:由于 tasklet_action() 处理方式是:一次性退出所有当前CPU上的 tasklet_struct,所以调用一次 tasklet_schedule(),该tasklet_struct只会被调度运行一次,如果需要重复执行,需要用户自己重复调用 tasklet_schedule。
转载于:https://my.oschina.net/yepanl/blog/3050052
Kernel tasklet相关推荐
- Linux kernel的中断子系统之(九):tasklet
返回目录:<ARM-Linux中断系统>. 总结: 二介绍了tasklet存在的意义. 三介绍了通过tasklet_struct来抽想一个tasklet,每个CPU维护一个tasklet链 ...
- linux中的tasklet机制【转】
转自:http://blog.csdn.net/yasin_lee/article/details/12999099 转自: http://www.kerneltravel.net/?p=143 中断 ...
- kernel笔记——中断
cpu与磁盘.网卡.键盘等外围设备(相对于cpu和内存而言)交互时,cpu下发I/O请求到这些设备后,相对cpu的处理能力而言,磁盘.网卡等设备需要较长时间完成请求处理. 那么在请求发出到处理完成这段 ...
- 【linux kernel】 中断处理-中断下半部【转】
转自:http://www.cnblogs.com/embedded-tzp/p/4453987.html 欢迎转载,转载时需保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地 ...
- 【kernel 中内存分配那点事】
首先呢作为车载bsp开发人员,写大量的内核代码是不现实的事情,多数都是修修改改,但是要有内核代码阅读浏览理解的能力,毕竟linux kernel 还是很nb 的,所有技术人员深入研究内核代码是必须的, ...
- vrml场景实例代码_高并发的中断下半部tasklet实例解析
本文转自AliDataOps 最近为了解决一个技术问题,需要用到内核里中断下半部的tasklet机制,使用过程遇到了非常有趣的问题.在解决问题过程中,也逐步加深了对tasklet机制的理解.本文把这些 ...
- 【Linux开发】linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet...
linux设备驱动归纳总结(六):3.中断的上半部和下半部--tasklet xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- softirq/tasklet/workqueue的区别
2011年威盛Linux software的笔试题,我想了半天,就想出了工作队列允许睡眠...真后悔驱动没能深入看看 softirq和tasklet都属于软中断,tasklet是softirq的特殊实 ...
- Linux中断 - tasklet
一.前言 对于中断处理而言,linux将其分成了两个部分,一个叫做中断handler(top half),属于不那么紧急需要处理的事情被推迟执行,我们称之deferable task,或者叫做bott ...
最新文章
- 2018 ACM博士论文奖公布:伯克利博士获奖,清华姚班马腾宇荣誉提名(附论文链接)...
- IDE接口驱动程序移植
- python turtle怎么用变量_Python Turtle绘图指定变量时出现问题
- 2009年美国大学计算机专业排名
- 《设计团队协作权威指南》—第1章1.3节甘为螺丝钉
- git使用—rebase还是merge
- c6011取消对null指针的引用_C/C++学习笔记——C提高:指针强化
- __declspec(naked)和__asm编写实践总结
- ant design的自定义主题 modifyVars无效的原因
- mysql 主备XtraBackup恢复
- UITextField对字符串的个数限制
- 培训ui设计要学编程吗?
- Google 已将“xxxx”标记为恶意扩展程序并阻止安装,解决方案
- 将一个javaBean中非空的属性合并到另一个javaBean中
- DIV向上滚动(类似新闻)
- 利用React 和ant-design 搭建cnode项目的随笔
- linux cat命令追加,linux cat命令
- 网络质量监控 - 守好入口第一关
- pigeon-remoting模块功能分析
- Java语言十五讲(总结)