首页 > 人文 > >
Linux内核中的软中断、tasklet和工作队列详解( 四 )
2026-06-03
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();}}
推荐阅读
济南城事|临港区拓展纤维入选市“一企一技术”研发中心
小米|2022年安卓之光!小米12 Ultra保护壳曝光:背部摄像头布局敲定
三代|“豪不过三,富不过六,穷不过九”,老祖宗的金字良言,受益终生
音乐|「a-nation online 2020」火热开唱 跨国阵容组团点燃舞台主场
位梦娱乐|航空公司宁可赔几十亿,也不允许乘客跳伞逃生,为什么飞机遇难
【】世卫组织:全球新冠肺炎确诊病例累计超2768万例
《夏天里的成长》公开课教案?《夏天里的成长》优质课教案
【综艺小剧透】除了被删掉的6集,女主也是大问题,共3部分原因,枕上书口碑下降
此人位列梁山108将第76位,才能足以进入天罡却一直被误会为废物
小懒猫yen|每天抢着送钱的人不断,捞金渠道令人叹为观止,和珅15年贪了8亿
市场|大量印钞是否会有损美元全球储备货币地位?美联储主席回应
#蓝景源#显像管电视机的巅峰:特丽珑,一项曾经挽救了索尼的技术
三角解密|民众:美政府不要太双标,媒体战升级!美媒或将被驱逐出境
盘点科技学生党的福音?,口罩垫杯评测:男女都用得上的好物件