本文最后更新于55 天前,其中的信息可能已经过时,如有错误请发送邮件到273925452@qq.com
文章目录[隐藏]
工作队列线程
工作队列线程 (Work Queue Threads)是一种内核对象,它使用一个或多个专用的线程,以先进先出(FIFO)的方式处理提交给它的“工作项”。每个工作项的核心是执行一个指定的处理函数。
这种机制的主要目的是将耗时或非常紧急的处理任务从对时间敏感的上下文(如中断服务程序 ISR 或高优先级线程)中“卸载”到一个优先级较低的线程中执行。
工作队列线程 (Work Queue Threads) vs 系统工作队列 (System Work Queue)
| 维度 | 工作队列线程 (概念) | 系统工作队列 (具体实例) |
|---|---|---|
| 定义 | 任意 struct k_work_q 启动后对应的后台线程 |
内核预定义的全局共享工作队列 |
| 数量 | 可创建多个(RAM 受限) | 最多一个(可选,按需启用) |
| 适用场景 | 定制优先级、栈、隔离阻塞/高负载任务 | 简单、低频、短执行任务 |
| 优先级/栈 | 启动时由应用决定 | 由 CONFIG_SYSTEM_WORKQUEUE_* 配置 |
| 资源隔离 | 良好,可避免互相影响 | 差,长时间任务会拖慢所有共享工作 |
| 典型使用 | 驱动后台 I/O、协议处理、长耗时/阻塞片段 | ISR 后延迟处理、轻量去抖、异步轻任务 |
| 何以分开描述 | 前者描述机制(抽象模型);后者描述其默认实现(具体实例) | 提醒用户区分“机制”与“默认工具” |
可延迟的工作 与 触发工作
二者都属于“非立即执行的工作触发机制”:
– 可延迟工作:基于时间(超时/重新调度)
– 触发工作:基于事件轮询 (poll events)
| 对比项 | 可延迟工作 (k_work_delayable) | 触发工作 (k_work_poll / k_work_poll_submit) |
|---|---|---|
| 触发条件 | 到达预设时间(deadline) | 任一监控的 poll 事件触发或超时 |
| 核心 API | k_work_init_delayable / k_work_schedule / k_work_reschedule | k_work_poll_init / k_work_poll_submit |
| 更新策略 | schedule: 不改旧截止时间;reschedule: 重设 | 提交一次后等待事件;事件完成后执行 |
| 典型用途 | 去抖、延迟聚合、超时后动作 | 资源可用通知、信号/管道/套接字事件 |
| 可重新安排 | 是(reschedule 提供语义差异) | 需取消后再重新提交 |
| 取消 API | k_work_cancel_delayable(_sync) | k_work_cancel()(等待前可成功,触发后无效) |
| 处理函数参数 | struct k_work * (需 delayable_from_work 转换) | struct k_work * |
| 常见陷阱 | 错误使用 busy/pending 决策是否提交 | 事件数组在整个生命周期必须保持有效 |
| 使用模式 | 周期:handler 内再 reschedule | 事件驱动:低功耗 + 无 busy loop |
| 内部机制 | 超时到期时入队 | 内核内部等待 poll,事件即入队 |
工作项生命周期
- 初始化 (Initialized): 工作项必须先通过 k_work_init() 或 K_WORK_DEFINE 初始化,这会关联一个处理函数并将其标记为空闲状态。
- 提交/排队 (Submitted/Queued): 通过 k_work_submit() 或 k_work_submit_to_queue() 将工作项提交到工作队列。此时,工作项状态变为已排队 (K_WORK_QUEUED)。
- 调度 (Scheduled): 对于可延迟的工作项 (struct k_work_delayable),使用 k_work_schedule() 等函数进行调度。工作项会进入 K_WORK_DELAYED 状态,等待超时后再被提交到队列。
- 运行 (Running): 工作队列线程从队列中取出该工作项并执行其处理函数。此时工作项处于运行状态 (K_WORK_RUNNING)。
- 完成/空闲 (Completed/Idle): 处理函数执行完毕后,工作项返回空闲状态,可以被再次提交。
注: 一个工作项可以同时处于多种状态。例如,它可能正在运行,同时被标记为正在取消 (K_WORK_CANCELING),并且又被重新排队等待下一次运行。任何处于非空闲状态的工作项都被认为是“待处理” (k_work_is_pending()) 或“繁忙” (k_work_busy_get())。
代码示例(普通 + 延迟 + 重新调度)
// 普通工作
static void normal_handler(struct k_work *w) {
printk("normal work\n");
}
// 延迟工作:最后事件后延迟 200 ms 再处理
static void delayed_handler(struct k_work *w) {
struct k_work_delayable *dw = k_work_delayable_from_work(w);
printk("delayed fire\n");
ARG_UNUSED(dw);
}
K_WORK_DEFINE(normal_w, normal_handler);
static struct k_work_delayable delayed_w;
void init_work(void) {
k_work_init_delayable(&delayed_w, delayed_handler);
}
void event_arrive(void) {
/* 最新事件推迟处理窗口(“最后一次后延迟”语义) */
(void)k_work_reschedule(&delayed_w, K_MSEC(200));
(void)k_work_submit(&normal_w);
}
配置选项
| 配置项 | 作用 | 默认/影响 | 适用场景 |
|---|---|---|---|
| CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE | 系统工作队列线程栈大小 | 不足会栈溢出 | handler 递归/调用复杂库 |
| CONFIG_SYSTEM_WORKQUEUE_PRIORITY | 系统工作队列优先级 | 越小越高 | 提升延迟敏感工作处理 |
| CONFIG_SYSTEM_WORKQUEUE_NO_YIELD | 处理后不主动让出 | 可能影响协作线程 | 需要最大吞吐(慎用) |
API 参考
API: https://docs.zephyrproject.org/latest/doxygen/html/group__workqueue__apis.html
官方文档:https://docs.zephyrproject.org/latest/kernel/services/threads/workqueue.html
了解 Heiweilu的小世界 的更多信息
订阅后即可通过电子邮件收到最新文章。







