news 2026/5/6 22:24:05

Linux驱动开发八股文:工作队列(Workqueue)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux驱动开发八股文:工作队列(Workqueue)

📚 Linux 驱动开发笔记:工作队列 (Workqueue)

一、 核心定义

工作队列是 Linux 内核中断下半部(Bottom Half)的一种重要机制。它允许你将耗时的、需要等待资源或可能导致休眠的任务,从中断处理函数(ISR)中推迟到稍后的进程上下文中执行。

  • 关键特性:运行于进程上下文,可以休眠
  • 执行主体:内核线程(如kworker/0:2)。

二、 为什么需要工作队列? (对比 Tasklet)

在内核中,中断下半部主要有两种选择,它们的区别在于“执行环境”:

特性Tasklet工作队列 (Workqueue)
执行上下文中断(软中断)上下文进程上下文
能否休眠绝不可以(会系统崩溃)可以(如使用msleep
访问用户空间不可以不可以(虽然在进程上下文,但没有用户页表)
优先级极高,仅次于硬中断较低,由调度器决定
代表身份借用当前进程的“皮”拥有独立的内核线程 (kworker)

三、 工作队列的运作机制

  1. 提交任务:驱动在 ISR 中通过schedule_work函数提交一个work_struct
  2. 排队等待:该任务进入系统默认的工作队列链表。
  3. 唤醒线程:内核唤醒对应的内核线程(kworker)。
  4. 执行任务kworker线程从链表中取出任务,调用你编写的处理函数。
  5. 结束/调度:处理函数完成后,kworker线程继续处理下一个任务,或者进入睡眠。

四、 核心 API 与编程步骤

1. 定义工作结构体与处理函数

处理函数的参数是结构体本身,通常通过container_of获取私有数据。

struct work_struct my_work; void my_work_func(struct work_struct *work) { // 这里可以休眠! // printk("current->comm: %s, pid: %d\n", current->comm, current->pid); }
2. 初始化 (Init)

probe函数中完成,将函数指针绑定到结构体。

// 动态初始化 INIT_WORK(&gpio_key->work, my_work_func); // 或者静态定义 // DECLARE_WORK(name, function);
3. 调度 (Schedule)

在中断上半部(ISR)中调用,触发异步执行。

static irqreturn_t gpio_key_isr(int irq, void *dev_id) { schedule_work(&gpio_key->work); // 只是挂入队列,不阻塞 return IRQ_HANDLED; }

五、 实验现象深度解析

根据实验日志:

[165328.733643] {WORK_FUNC:}the process is kworker/0:2, its pid is 1722
  1. 身份证明current->commkworker/0:2,证明了工作队列不再是“借用”别人的身份,而是由内核专属的“工人”线程在干活。
  2. PID 1722:这是一个真实的进程 ID。在 Linux 中,凡是有 PID 的都能被调度器控制,这就是它为什么可以休眠的根本原因。
  3. 时序关系:日志中TASKLET总是先于WORK_FUNC打印。这是因为 Tasklet 优先级更高,在中断返回的瞬间执行;而 Workqueue 需要等待调度器切换到kworker线程,存在毫秒级的调度延迟。

六、 注意事项与避坑指南

  1. 顺序阻塞:默认的工作队列由同一个kworker线程依序处理。如果你在一个 Work 函数里写了while(1)或休眠太久,会堵塞同一个队列里的其他工作
  2. 重入性:如果在 Work 还没执行完时又发生了中断并schedule_work,内核通常不会重复启动同一个 Work 实例,它会等待当前运行的结束后再决定是否再次触发。
  3. API 演进:4.x 以后内核引入了CMWQ (Concurrency Managed Workqueue),它能更聪明地在多核之间分配任务,避免单个耗时任务卡死整个 CPU 的工作队列。

七、 总结:何时选择工作队列?

  • 任务很重(如:读取 1MB 的 Flash 数据)。
  • 需要等待(如:等待某个信号量、互斥锁)。
  • 需要延时(如:逻辑要求按键按下后等待 100ms 再读取)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 16:45:37

PostgreSQL 图数据库化方案:Apache AGE 的引入与实践

一、介绍图数据库擅长处理复杂关联关系,而 PostgreSQL 擅长事务型数据管理。Apache AGE 通过扩展方式将图数据库能力引入 PostgreSQL,使其在保持原有稳定性与生态优势的同时,补齐了图数据建模与查询能力的短板。这种“关系型数据库 图模型”…

作者头像 李华
网站建设 2026/4/29 9:16:03

【倒计时一天】2025第八届金猿大数据产业发展论坛——暨AI InfraData Agent趋势论坛丨颁奖典礼·上海

第八届金猿颁奖典礼“重要提示➩ 活动报名&现场签到有好礼,先到先得点此小程序链接可报名参会大数据产业创新服务媒体——聚焦数据 改变商业数智产业正站在变革的临界点上。过去十年,大数据从技术概念演进为基础设施,完成了产业奠基&…

作者头像 李华
网站建设 2026/5/2 16:41:40

Figma中文插件完全配置指南:告别英文界面困扰

Figma中文插件完全配置指南:告别英文界面困扰 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma复杂的英文界面而头疼吗?面对专业设计工具,…

作者头像 李华
网站建设 2026/5/3 22:16:13

Figma中文界面本地化:设计师专属的语言解决方案

Figma中文界面本地化:设计师专属的语言解决方案 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 语言障碍的痛点与解决方案 对于国内设计从业者而言,Figma作为专…

作者头像 李华
网站建设 2026/5/6 19:15:23

Day 33:【99天精通Python】日志记录 (Logging) - 告别 Print 调试

Day 33:【99天精通Python】日志记录 (Logging) - 告别 Print 调试 前言 欢迎来到第33天! 在之前的编程练习中,当我们需要调试代码或者查看程序运行状态时,最常用的办法就是 print()。 但是在真正的项目开发(尤其是服务…

作者头像 李华
网站建设 2026/5/6 17:25:38

基于STSW-LINK007工具的STLink升级实战案例

STLink固件升级实战:从避坑到精通的完整指南 在嵌入式开发的世界里,调试器就像医生的听诊器——看不见它的时候风平浪静,一旦“连不上”、“下不进程序”,整个项目进度立刻停摆。而当你发现原因竟是 调试器固件太老不支持新芯片…

作者头像 李华