工作队列
2026/7/16大约 7 分钟内核组件内核延迟执行工作队列Bottom-Half
工作队列
📚 本节导读
学习时长: 约 20 分钟
难度级别: ⭐⭐⭐☆☆
前置知识: 任务管理、信号量、中断管理
工作队列(Workqueue)是 OneOS 中用于延迟执行工作的机制。它将工作项提交到工作队列中,由专门的工作线程(worker thread)异步执行。这类似于 Linux 内核中的 workqueue,是 Bottom-Half 处理的经典实现方式。
🎯 学习目标
- 理解工作队列的核心概念:延迟执行、异步处理
- 掌握工作队列和工作项的创建与初始化
- 掌握工作项的提交(带延迟)和取消操作
- 了解系统工作队列的使用
- 理解工作项的三个阶段状态
一、工作队列概念
1.1 什么是工作队列
工作队列由一个工作线程和一个工作项链表组成。当有工作项被提交时,工作线程被唤醒,从链表中取出工作项并执行其回调函数。
┌─────────────────────────────────────────────────────────────────┐
│ 工作队列模型 │
│ │
│ ┌──────────┐ os_work_run() ┌──────────────────────────┐ │
│ │ 任务 A │ ────────────────→ │ 工作队列 │ │
│ │(提交者) │ 提交工作项 │ │ │
│ └──────────┘ │ ┌──────┐ ┌──────┐ │ │
│ │ │Work 1│→│Work 2│ │ │
│ ┌──────────┐ os_work_run() │ └──────┘ └──────┘ │ │
│ │ ISR │ ────────────────→ │ ↑ │ │
│ │(中断) │ │ 工作线程取出并执行 │ │
│ └──────────┘ │ │ │
│ │ ┌──────────────────┐ │ │
│ ┌──────────┐ │ │ Worker Thread │ │ │
│ │ 任务 B │ │ │ (优先级可配置) │ │ │
│ │(提交者) │ │ │ while(1) { │ │ │
│ └──────────┘ │ │ 取出工作项 │ │ │
│ │ │ 执行 work->func │ │ │
│ │ │ } │ │ │
│ │ └──────────────────┘ │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘1.2 工作项的三个阶段
工作项从提交到执行经历三个阶段:
┌──────────────┐ 提交(带延迟) ┌──────────────┐ 延迟到期 ┌──────────────┐
│ IDLE │ ──────────────────→ │ DELAY │ ──────────────→ │ PENDING │
│ 空闲 │ │ 延迟等待 │ │ 等待执行 │
│ │ │ (定时器等待) │ │ (在队列中) │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
┌──────────────┐ │ 工作线程执行
│ IDLE │ ←─────────┘
│ (回调执行完) │
└──────────────┘| 阶段 | 宏 | 说明 |
|---|---|---|
| IDLE | OS_WORK_STAGE_IDLE (0x0) | 工作项空闲,未提交或已完成 |
| DELAY | OS_WORK_STAGE_DELAY (0x1) | 工作项已提交带延迟,等待延迟到期 |
| PENDING | OS_WORK_STAGE_PENDING (0x2) | 工作项在队列中等待工作线程执行 |
1.3 使用场景
| 场景 | 说明 |
|---|---|
| Bottom-Half 处理 | 中断上半部只做关键操作,耗时操作交给工作队列 |
| 延迟执行 | 需要在指定时间后执行的操作 |
| 异步操作 | 不需要等待结果的操作,提交后即可返回 |
| 串行化处理 | 多个提交者提交的工作项在工作线程中串行执行 |
二、API 详解
以下 API 定义在 kernel/include/os_workqueue.h 中:
#include <os_workqueue.h>注意:使用工作队列需要在
oneos_config.h中启用OS_USING_WORKQUEUE宏。系统工作队列还需要OS_USING_SYSTEM_WORKQUEUE。
2.1 静态定义宏
#define OS_WORKQUEUE_DEFINE(name) os_workqueue_dummy_t name /* 定义工作队列控制块 */
#define OS_WORK_DEFINE(name) os_work_dummy_t name /* 定义工作项控制块 */2.2 创建工作队列
os_workqueue_id os_workqueue_create(os_workqueue_dummy_t *queue_cb,
const char *name,
void *stack_begin,
uint32_t stack_size,
uint8_t priority,
int32_t cpu_index);| 参数 | 说明 |
|---|---|
queue_cb | 工作队列控制块指针。静态创建时传入 OS_WORKQUEUE_DEFINE 定义的变量地址;动态创建时传 OS_NULL |
name | 工作队列名称 |
stack_begin | 工作线程栈起始地址。传 OS_NULL 则自动分配 |
stack_size | 工作线程栈大小 |
priority | 工作线程优先级 |
cpu_index | 工作线程绑定的 CPU 索引(SMP 相关)。传 -1 表示不绑定 |
| 返回值 | 成功返回工作队列 ID,失败返回 OS_NULL |
2.3 初始化工作项
os_work_id os_work_init(os_work_dummy_t *work, void (*func)(void *data), void *data);| 参数 | 说明 |
|---|---|
work | 工作项控制块指针(OS_WORK_DEFINE 定义的变量地址) |
func | 工作项回调函数,工作线程执行时调用 |
data | 传递给回调函数的参数 |
| 返回值 | 成功返回工作项 ID,失败返回 OS_NULL |
2.4 反初始化工作项
void os_work_deinit(os_work_id work_id);2.5 提交工作项
os_err_t os_work_run(os_workqueue_id queue_id, os_work_id work_id, os_tick_t delay_time);| 参数 | 说明 |
|---|---|
queue_id | 工作队列 ID |
work_id | 工作项 ID |
delay_time | 延迟时间(tick 数)。0 表示立即提交,> 0 表示延迟指定 tick 后执行 |
| 返回值 | OS_EOK 成功;OS_EBUSY 工作项已在队列中 |
2.6 取消工作项
os_err_t os_work_stop(os_work_id work_id, os_bool_t sync);| 参数 | 说明 |
|---|---|
work_id | 工作项 ID |
sync | OS_TRUE:同步取消,等待工作项执行完毕(如果正在执行);OS_FALSE:异步取消 |
| 返回值 | OS_EOK 成功 |
2.7 系统工作队列
os_err_t os_sys_work_run(os_work_id work_id, os_tick_t delay_time);将工作项提交到系统预置的工作队列。不需要用户自己创建工作队列,适用于简单场景。
需要启用
OS_USING_SYSTEM_WORKQUEUE。
三、代码示例
3.1 基本使用:延迟执行
#include <oneos_config.h>
#include <os_task.h>
#include <os_workqueue.h>
OS_WORKQUEUE_DEFINE(g_my_wq);
OS_WORK_DEFINE(g_my_work);
/* 工作项回调函数 */
void my_work_func(void *data)
{
int *counter = (int *)data;
(*counter)++;
printf("Work executed! Counter = %d\n", *counter);
}
void workqueue_basic_example(void)
{
os_workqueue_id wq_id;
os_work_id work_id;
static int counter = 0;
/* 创建工作队列 */
wq_id = os_workqueue_create(&g_my_wq, "my_wq",
OS_NULL, /* 自动分配栈 */
1024, /* 栈大小 */
20, /* 优先级 */
-1); /* 不绑定 CPU */
/* 初始化工作项 */
work_id = os_work_init(&g_my_work, my_work_func, &counter);
/* 立即提交工作项 */
os_work_run(wq_id, work_id, 0);
/* 延迟 1000 ticks 后执行 */
os_work_run(wq_id, work_id, 1000);
}3.2 使用系统工作队列
OS_WORK_DEFINE(g_sys_work);
void sys_work_func(void *data)
{
const char *msg = (const char *)data;
printf("System workqueue: %s\n", msg);
}
void sys_workqueue_example(void)
{
os_work_id work_id;
/* 初始化工作项 */
work_id = os_work_init(&g_sys_work, sys_work_func, "Hello from sys wq!");
/* 提交到系统工作队列,延迟 500 ticks 执行 */
os_sys_work_run(work_id, 500);
}3.3 Bottom-Half 模式:中断与工作队列配合
OS_WORK_DEFINE(g_bh_work);
typedef struct
{
uint8_t *data;
int length;
} bh_data_t;
/* Bottom-Half 处理函数 */
void bottom_half_handler(void *data)
{
bh_data_t *bh = (bh_data_t *)data;
printf("Bottom-half: processing %d bytes\n", bh->length);
/* 执行耗时的数据处理 */
for (int i = 0; i < bh->length; i++)
{
process_byte(bh->data[i]);
}
/* 释放数据 */
free(bh->data);
free(bh);
}
/* 中断服务程序(上半部) */
void uart_rx_isr(void)
{
bh_data_t *bh;
/* 上半部:快速接收数据 */
bh = (bh_data_t *)malloc(sizeof(bh_data_t));
if (bh == OS_NULL)
return;
bh->length = 128;
bh->data = (uint8_t *)malloc(bh->length);
if (bh->data == OS_NULL)
{
free(bh);
return;
}
/* 从硬件读取数据 */
for (int i = 0; i < bh->length; i++)
{
bh->data[i] = read_uart_byte();
}
/* 提交 Bottom-Half 到系统工作队列 */
os_sys_work_run(g_bh_work_id, 0);
}3.4 动态创建与销毁
void workqueue_dynamic_example(void)
{
os_workqueue_id wq_id;
os_work_id work_id;
os_work_dummy_t *work_cb;
/* 动态创建工作队列 */
wq_id = os_workqueue_create(OS_NULL, "dynamic_wq",
OS_NULL, 1024, 15, -1);
/* 动态分配工作项控制块 */
work_cb = (os_work_dummy_t *)malloc(sizeof(os_work_dummy_t));
/* 初始化工作项 */
work_id = os_work_init(work_cb, my_work_func, OS_NULL);
/* 提交工作项 */
os_work_run(wq_id, work_id, 0);
/* 使用完后,反初始化并释放 */
os_work_deinit(work_id);
free(work_cb);
/* 注意:工作队列的销毁需要确保没有待处理的工作项 */
}3.5 取消工作项
OS_WORK_DEFINE(g_cancel_work);
void cancel_work_func(void *data)
{
printf("This work should be cancelled\n");
}
void cancel_work_example(void)
{
os_work_id work_id;
work_id = os_work_init(&g_cancel_work, cancel_work_func, OS_NULL);
/* 提交延迟工作项 */
os_work_run(g_wq_id, work_id, 5000); /* 5 秒后执行 */
/* 在延迟到期前取消 */
os_task_sleep(1000); /* 等待 1 秒 */
os_err_t ret = os_work_stop(work_id, OS_FALSE); /* 异步取消 */
if (ret == OS_EOK)
{
printf("Work cancelled successfully\n");
}
}3.6 同步取消:等待工作项完成
void sync_stop_work_example(void)
{
os_work_id work_id = os_work_init(&g_work, my_work_func, OS_NULL);
os_work_run(g_wq_id, work_id, 0);
/* 同步取消:如果工作项正在执行,等待其完成 */
os_work_stop(work_id, OS_TRUE);
printf("Work is guaranteed to be stopped\n");
}📝 本节小结
工作队列是 OneOS 中实现延迟执行和 Bottom-Half 处理的核心机制,关键要点:
- 异步执行:工作项提交后立即返回,由工作线程异步执行回调函数
- 延迟执行:通过
delay_time参数可以指定延迟时间,实现定时执行 - 三个阶段:IDLE(空闲)→ DELAY(延迟等待)→ PENDING(等待执行)
- 系统工作队列:
os_sys_work_run使用系统预置的工作队列,简单场景无需自行创建 - Bottom-Half 模式:中断上半部快速处理,将耗时操作提交到工作队列
- 取消支持:
os_work_stop可以取消尚未执行的工作项,支持同步和异步两种模式