目录

概述

1 k_work_schedule函数

1.1 函数介绍

1.2  工作流程

1.3 关键特性

1.4 与相关函数对比

 2 工作队列的其他API

2.1 . 初始化与提交

2.2 队列管理

2.3   控制与状态

2.4  系统工作队列 vs 自定义工作队列

3 典型应用

3.1 延时触发功能

3.2 精确周期任务

4 高级特性与优化技巧

5 性能关键设计

5.1 主要特性

5.2  最佳实践


概述

本主要介绍k_work_schedule函数功能和Zephyr RTOS 的工作队列(Workqueue),Zephyr RTOS 的工作队列(Workqueue)是其异步任务处理的核心机制,专为资源受限的嵌入式系统设计。它提供了一种高效、线程安全的方式执行延迟任务、中断下半部处理以及周期性操作。

1 k_work_schedule函数

k_work_schedule 是实时操作系统(特别是 Zephyr RTOS)中用于延迟执行工作项(work item) 的核心函数。它属于工作队列(workqueue)子系统,用于实现异步、延迟的任务执行。以下是详细解析:

1.1 函数介绍

1)函数原型

int k_work_schedule(struct k_work_delayable *dwork, k_timeout_t delay);

2)参数介绍

参数 类型 说明
dwork struct k_work_delayable* 指向可延迟工作项的指针(需先初始化)
delay k_timeout_t 延迟时间:
K_NO_WAIT: 立即提交
K_FOREVER: 取消调度
- 正整数值: 具体延迟

3)功能介绍

  1. 延迟任务调度

    • 将工作项 dwork 安排在指定的 delay 时间后执行

    • 时间单位:毫秒(如 K_MSEC(100))或绝对时间点(如 K_TIMEOUT_ABS_T(ms)

  2. 取消与重置

    • 若该工作项已处于调度状态,自动取消原计划并重新计时

    • 支持动态调整延迟时间(用于实现看门狗、超时重试等场景)

  3. 线程安全

    • 可在中断上下文调用(如 ISR 中调度延迟任务)

    • 内部使用锁保护工作队列状态

1.2  工作流程

具体步骤如下:

1) 初始化工作项

struct k_work_delayable my_work;
k_work_init_delayable(&my_work, my_handler); // 绑定处理函数

2) 调度延迟执行

// 在中断中调度:200ms后执行
k_work_schedule(&my_work, K_MSEC(200));

3)到期自动执行

  • 系统定时器到期后,工作项被提交到绑定的工作队列

  • 工作队列线程调用预定义的 my_handler() 函数

 1.3 关键特性

特性 说明
异步执行 工作项处理函数在工作队列线程中运行,与调用者隔离
动态调度 支持运行时修改延迟时间
取消机制 通过 k_work_cancel_delayable() 可手动取消未执行的任务
资源高效 共享工作队列线程,避免为每个任务创建独立线程
ISR 安全 唯一可在中断上下文中安全使用的延迟执行机制

1.4 与相关函数对比

函数 特点 执行上下文限制
k_work_schedule() 延迟执行(可取消/重置) 允许在 ISR 中调用
k_work_submit() 立即提交到工作队列(非延迟) 允许在 ISR 中调用
k_timer_start() 纯定时器(无工作队列集成) 允许在 ISR 中调用
k_thread_create() 创建独立线程(开销大) 不能在 ISR 中调用

 2 工作队列的其他API

2.1 . 初始化与提交

API 功能说明 ISR 安全
k_work_init() 初始化标准工作项
k_work_submit() 立即提交到系统队列
k_work_submit_to_queue() 提交到指定队列
k_work_init_delayable() 初始化可延迟工作项
k_work_schedule() 调度延迟执行(核心调度函数)
k_work_reschedule() 强制重新调度延迟工作项

 2.2 队列管理

API 功能说明
k_work_queue_start() 启动自定义队列线程
k_work_queue_drain() 排空队列并阻止新任务
k_work_flush() 等待特定工作项完成

2.3   控制与状态

API 功能说明
k_work_cancel() 取消未执行的标准工作项
k_work_cancel_delayable() 取消延迟工作项
k_work_busy_get() 获取工作项状态(0=空闲, 1=提交, 2=运行)

2.4  系统工作队列 vs 自定义工作队列

特性 系统工作队列 (k_sys_work_q) 自定义工作队列
线程优先级 内核级负优先级 (-1) 用户可配置 (默认 0)
栈大小 固定 (CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE) 用户定义
使用场景 轻量级通用任务 耗时/专用任务
资源开销 共享资源,零新增开销 每队列额外占用 1 线程 + 栈空间
典型应用 传感器数据采集、网络回调 文件系统操作、加密计算

3 典型应用

 3.1 延时触发功能

1) 定义k_work_delayable

static struct k_work_delayable adv_work;
static struct k_work_delayable sleep_work;

2) 初始化k_work_init_delayable

void app_work_start( void )
{    

    // initial work queue 
    k_work_init_delayable(&adv_work, start_adv_work);
    k_work_init_delayable(&sleep_work, stop_adv_work);
    

    k_work_schedule(&adv_work, K_NO_WAIT);
}

3) 定义执行函数  

static void stop_adv_work(struct k_work *work)
{
    k_work_schedule(&adv_work, K_MINUTES(30));
    printk("stop to beacon, and system will sleep \n");

}

static void start_adv_work(struct k_work *work)
{
    k_work_schedule(&sleep_work, K_SECONDS(30));   
    printk("start to beacon, interval = %d s \n", interval );
}

3.2 精确周期任务

void periodic_handler(struct k_work *work) {
    do_task();
    
    // 每 100ms 重新调度自身
    k_work_schedule(
        container_of(work, struct k_work_delayable, work),
        K_MSEC(100)
    );
}

// 初始化延迟工作项
k_work_init_delayable(&periodic_work, periodic_handler);
k_work_schedule(&periodic_work, K_NO_WAIT); // 立即启动

高级特性与优化技巧

1) 工作项池 (Work Pool)

  • 预初始化静态工作项数组

  • 避免运行时内存分配碎片

    K_WORK_DEFINE(work_pool[10], handler);

2) 链式工作项 (Chained Work)

  • 在工作处理函数中提交新工作项

  • 实现任务流水线

    void stage1(struct k_work *w) {
        process_stage1();
        k_work_submit(&stage2_work); // 触发下一阶段
    }

3)  动态延迟调整

  • 根据系统状态修改调度时间

    void adaptive_handler(struct k_work *work) {
        int new_delay = calculate_optimal_delay();
        k_work_reschedule(dwork, K_MSEC(new_delay));
    }

4) 工作项标记

  • 使用 work->flags 传递状态

    #define WORK_FLAG_URGENT BIT(0)
    work.flags |= WORK_FLAG_URGENT;

性能关键设计

5.1 主要特性

  1. 零拷贝提交

    • 工作项提交仅复制指针(约 10 个 CPU 周期)

  2. 无锁队列操作

    • 使用原子操作管理任务队列

    • 中断提交无需关中断

  3. 内存占用优化

    对象 内存占用 (bytes)
    struct k_work 20
    struct k_work_q 56
    线程栈 (典型) 256-2048
  4. 实时性保障

    • 工作项处理最坏延迟 = 当前项执行时间 + 线程切换时间

5.2  最佳实践

  • 避免在工作处理函数中阻塞

  • ISR 提交的工作项延迟应 < 5ms

  • 耗时任务 (>1ms) 使用自定义队列

  • 使用 k_work_flush() 在关机前确保任务完成

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐