首页 > 人文 > >
Linux内核中的软中断、tasklet和工作队列详解( 四 )
2026-06-25
struct tasklet_struct{struct tasklet_struct *next;//将多个tasklet链接成单向循环链表unsigned long state;//TASKLET_STATE_SCHED(Tasklet is scheduled for execution)TASKLET_STATE_RUN(Tasklet is running (SMP only))atomic_t count;//0:激活tasklet 非0:禁用taskletvoid (*func)(unsigned long); //用户自定义函数unsigned long data;//函数入参};static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);//低优先级static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);//高优先级相关API
#define DECLARE_TASKLET(name, func, data) \struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }//定义名字为name的非激活tasklet#define DECLARE_TASKLET_DISABLED(name, func, data) \struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data } //定义名字为name的激活taskletvoid tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), unsigned long data)//动态初始化taskletstatic inline void tasklet_disable(struct tasklet_struct *t)//函数暂时禁止给定的tasklet被tasklet_schedule调度 , 直到这个tasklet被再次被enable;若这个tasklet当前在运行, 这个函数忙等待直到这个tasklet退出static inline void tasklet_enable(struct tasklet_struct *t)//使能一个之前被disable的tasklet;若这个tasklet已经被调度, 它会很快运行 。 tasklet_enable和tasklet_disable必须匹配调用, 因为内核跟踪每个tasklet的"禁止次数"static inline void tasklet_schedule(struct tasklet_struct *t)//调度 tasklet 执行 , 如果tasklet在运行中被调度, 它在完成后会再次运行; 这保证了在其他事件被处理当中发生的事件受到应有的注意. 这个做法也允许一个 tasklet 重新调度它自己tasklet_hi_schedule(struct tasklet_struct *t)//和tasklet_schedule类似 , 只是在更高优先级执行 。 当软中断处理运行时, 它处理高优先级 tasklet 在其他软中断之前 , 只有具有低响应周期要求的驱动才应使用这个函数, 可避免其他软件中断处理引入的附加周期.tasklet_kill(struct tasklet_struct *t)//确保了 tasklet 不会被再次调度来运行 , 通常当一个设备正被关闭或者模块卸载时被调用 。 如果 tasklet 正在运行, 这个函数等待直到它执行完毕 。 若 tasklet 重新调度它自己 , 则必须阻止在调用 tasklet_kill 前它重新调度它自己 , 如同使用 del_timer_sync 实现原理
static inline void tasklet_schedule(struct tasklet_struct *t){if (!test_and_set_bit(TASKLET_STATE_SCHED, }void __tasklet_schedule(struct tasklet_struct *t){unsigned long flags;local_irq_save(flags);t->next = NULL;*__get_cpu_var(tasklet_vec).tail = t;__get_cpu_var(tasklet_vec).tail = //加入低优先级列表raise_softirq_irqoff(TASKLET_SOFTIRQ);//触发软中断local_irq_restore(flags);}tasklet执行过程 TASKLET_SOFTIRQ对应执行函数为tasklet_action , HI_SOFTIRQ为tasklet_hi_action , 以tasklet_action为例说明 , tasklet_hi_action大同小异 。 static void tasklet_action(struct softirq_action *a){struct tasklet_struct *list;local_irq_disable();list = __get_cpu_var(tasklet_vec).head;__get_cpu_var(tasklet_vec).head = NULL;__get_cpu_var(tasklet_vec).tail = //取得tasklet链表local_irq_enable();while (list) {struct tasklet_struct *t = list;list = list->next;if (tasklet_trylock(t)) {if (!atomic_read(t->func(t->data);tasklet_unlock(t);continue;}tasklet_unlock(t);}//如果t->count的值不等于0 , 说明这个tasklet在调度之后 , 被disable掉了 , 所以会将tasklet结构体重新放回到tasklet_vec链表 , 并重新调度TASKLET_SOFTIRQ软中断 , 在之后enable这个tasklet之后重新再执行它local_irq_disable();t->next = NULL;*__get_cpu_var(tasklet_vec).tail = t;__get_cpu_var(tasklet_vec).tail =__raise_softirq_irqoff(TASKLET_SOFTIRQ);local_irq_enable();}}
推荐阅读
小车|又一起!10岁女孩蹲地整理书包,小车从身上碾过!警方连夜通报
万象之昼夜观察|看到怀疑人生的10张照片,最后一张到底是咋回事?
考个消防证就能躺赚10万?女子带老公、朋友一起发财,结果……
我的黑色迷你裙|什么样的人是值得珍惜的“贵人”,人的一生
沐辰王者菌|世冠1/4决赛分均输出榜单出炉,刺痛成功登顶,MTG两人上榜
阿丽塔▲强烈推荐4部CG动画电影,每一部让你嗨到爆
windows10|Ubuntu在Linux改造上获得Windows 10
香港发生罕见AI诈骗案 涉案金额高达1.84亿人民币
|阴阳师百闻牌:一根羽毛引发的血案,百闻牌以津真天的黄金羽
体坛焦点|这粒脚后跟进球攻破了哪队球门?,「足坛趣味问答」C罗专场
「生肖」让男人“移不开眼”的3大生肖女,都是内外兼修气质佳的完美女人
艾米谈社会心理测试:哪一个最像富婆?测你为了赚钱需要付出什么代价
小学生补钙吃什么食物最好最快 小学生补钙的方法是什么
「舆情」不要把广大关心公共事件的媒体和网民当成“假想敌”
阵风战机|印度做好空袭准备,5架阵风战机随时出动,自信能突破歼20的拦截
拔河|“?主管是觉得我太闲逗我的吗?那么厚一本让我录进电脑,该怎么办哈?”