Zephyr RTOS 工作队列函数(k_work_reschedule )的应用方法介绍

目录

概述

[1 函数功能介绍](#1 函数功能介绍)

[1.1 函数原型](#1.1 函数原型)

[1.2 k_work工作队列使用流程](#1.2 k_work工作队列使用流程)

[1.3 其他相关函数](#1.3 其他相关函数)

[2 常用的示例](#2 常用的示例)

[2.1 基本用法](#2.1 基本用法)

[2.2 动态分配延迟工作项](#2.2 动态分配延迟工作项)

[2.3 检查并重新安排](#2.3 检查并重新安排)

[2.4 使用绝对时间](#2.4 使用绝对时间)

[3 k_work_reschedule 的非阻塞特性](#3 k_work_reschedule 的非阻塞特性)

[4 实现"异步等待"的模式](#4 实现"异步等待"的模式)

[4.1 回调通知](#4.1 回调通知)

[4.2 状态机](#4.2 状态机)

[4.3 性能注意事项](#4.3 性能注意事项)

[4.4 常见问题和解决方法](#4.4 常见问题和解决方法)


概述

k_work_reschedule 函数在 Zephyr RTOS 中用于重新安排延迟工作项(delayed work)的执行时间。该函数在需要动态调整定时任务时非常有用,特别是在实现防抖、超时重试、周期性任务等场景。本文详细介绍其用法。

1 函数功能介绍

1.1 函数原型

k_work_reschedule 函数原型如下:

cpp 复制代码
int k_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay);
  • 参数说明
参数 类型 描述
dwork struct k_work_delayable * 指向延迟工作项的指针
delay k_timeout_t 新的延迟时间

返回值:

  • 0:成功重新安排

  • -EINVAL:无效参数

  • -EALREADY:工作项已在运行或已完成

1.2 k_work工作队列使用流程

step-1: 定义队列变量

cpp 复制代码
static struct k_work_delayable demo_rec_timeout;

step-2: 定义callback函数

cpp 复制代码
static void callback_timeout_handler(struct k_work *item)
{
   // do something 

}

step-3: 执行回调函数

cpp 复制代码
#define BLE_WAIT_TIME                   300
#define BLE_WAIT_FOR_RECV_DELAY         K_MSEC(BLE_WAIT_TIME)


static void do_timeout_reschedule( void )
{
    k_work_reschedule(&demo_rec_timeout, BLE_WAIT_FOR_RECV_DELAY);
}

step-4: 初始化k_work

cpp 复制代码
void ble_rec_timeout_init( void )
{
    k_work_init_delayable(&demo_rec_timeout, demo_rec_timeout_handler);
}

1.3 其他相关函数

函数 描述 是否取消之前的安排
k_work_schedule() 首次安排延迟工作
k_work_reschedule() 重新安排延迟工作
k_work_schedule_for_queue() 安排到指定队列

2 常用的示例

2.1 基本用法

cpp 复制代码
#include <zephyr/kernel.h>
#include <zephyr/sys/work.h>

// 定义工作处理函数
void my_work_handler(struct k_work *work)
{
    printk("Work executed!\n");
}

// 定义延迟工作项
K_WORK_DELAYABLE_DEFINE(my_dwork, my_work_handler);

void main(void)
{
    // 第一次安排:1秒后执行
    k_work_reschedule(&my_dwork, K_SECONDS(1));
    
    // 在1秒内重新安排:改为2秒后执行
    k_work_reschedule(&my_dwork, K_SECONDS(2));
}

2.2 动态分配延迟工作项

cpp 复制代码
struct k_work_delayable *dwork;

void init_work(void)
{
    // 动态分配延迟工作项
    dwork = k_malloc(sizeof(struct k_work_delayable));
    
    // 初始化
    k_work_init_delayable(dwork, my_work_handler);
    
    // 安排工作
    k_work_reschedule(dwork, K_MSEC(500));
}

2.3 检查并重新安排

cpp 复制代码
void reschedule_if_needed(void)
{
    // 检查工作项是否在等待队列中
    if (k_work_delayable_is_pending(&my_dwork)) {
        // 取消之前的安排,重新设置
        k_work_reschedule(&my_dwork, K_SECONDS(5));
    } else {
        // 第一次安排
        k_work_schedule(&my_dwork, K_SECONDS(5));
    }
}

2.4 使用绝对时间

cpp 复制代码
// 安排到特定时间点执行
k_timepoint_t future_time = sys_timepoint_calc(K_SECONDS(10));
k_work_reschedule(&my_dwork, future_time);

3 k_work_reschedule 的非阻塞特性

1) 立即返回

cpp 复制代码
// 示例:调用立即返回,不等待工作项执行
int ret = k_work_reschedule(&my_dwork, K_SECONDS(1));
// 立即执行到这里,不阻塞
printk("立即返回,返回值: %d\n", ret);

2) 从任何上下文调用

cpp 复制代码
// 中断服务程序(ISR)中安全调用
void isr_handler(const void *arg)
{
    // 中断上下文中调用 - 完全安全
    k_work_reschedule(&irq_work, K_MSEC(10));
    // 立即返回,不阻塞中断处理
}

3) 不会等待工作项执行

cpp 复制代码
void test_non_blocking(void)
{
    printk("开始安排工作\n");
    
    // 安排5秒后执行
    k_work_reschedule(&delayed_work, K_SECONDS(5));
    
    // 立即继续执行,不等待5秒
    printk("安排完成,继续执行其他任务\n");
    
    // 这里的工作会立即执行,而不是等待5秒
    do_other_tasks();
}

与阻塞函数的对比:

1) 阻塞方式(不要在工作项中使用)

cpp 复制代码
void blocking_work_handler(struct k_work *work)
{
    // 错误示例:这会使工作队列线程阻塞
    k_sleep(K_SECONDS(5));  // ❌ 阻塞!
    printk("5秒后...\n");
}

// 主线程中调用
void main_task(void)
{
    k_work_reschedule(&blocking_work, K_SECONDS(1));
    // 虽然这里立即返回,但工作队列线程会被阻塞!
}

2) 非阻塞方式(正确做法)

cpp 复制代码
void non_blocking_work_handler(struct k_work *work)
{
    // 立即执行耗时任务
    do_intensive_processing();
    // 或者分解任务
    continue_processing_later(work);
}

// 如果需要延迟,使用重新安排
void continue_processing_later(struct k_work *work)
{
    struct k_work_delayable *dwork = 
        k_work_delayable_from_work(work);
    
    // 非阻塞地重新安排自己
    k_work_reschedule(dwork, K_MSEC(100));
}

4 实现"异步等待"的模式

4.1 回调通知

cpp 复制代码
struct async_context {
    struct k_work_delayable work;
    struct k_sem completion;
    void *result;
};

void async_work_handler(struct k_work *work)
{
    struct async_context *ctx = 
        CONTAINER_OF(work, struct async_context, work.work);
    
    // 执行异步任务
    ctx->result = perform_async_operation();
    
    // 通知等待者
    k_sem_give(&ctx->completion);
}

// 调用者
void caller_function(void)
{
    struct async_context ctx;
    k_sem_init(&ctx.completion, 0, 1);
    k_work_init_delayable(&ctx.work, async_work_handler);
    
    // 启动异步工作 - 立即返回
    k_work_reschedule(&ctx.work, K_NO_WAIT);
    
    // 可以做其他事情...
    do_other_work();
    
    // 等待完成(如果需要)
    k_sem_take(&ctx.completion, K_FOREVER);
}

4.2 状态机

cpp 复制代码
enum work_state {
    STATE_IDLE,
    STATE_PROCESSING,
    STATE_COMPLETE
};

struct stateful_work {
    struct k_work_delayable dwork;
    enum work_state state;
    int step;
};

void state_machine_work_handler(struct k_work *work)
{
    struct stateful_work *sw = 
        CONTAINER_OF(k_work_delayable_from_work(work), 
                    struct stateful_work, dwork);
    
    switch (sw->step) {
    case 0:
        // 第一步
        start_processing();
        sw->step = 1;
        // 立即安排下一步
        k_work_reschedule(&sw->dwork, K_NO_WAIT);
        break;
        
    case 1:
        // 第二步
        continue_processing();
        sw->step = 2;
        // 延迟执行下一步
        k_work_reschedule(&sw->dwork, K_MSEC(50));
        break;
        
    case 2:
        // 完成
        finish_processing();
        sw->state = STATE_COMPLETE;
        break;
    }
}

4.3 性能注意事项

1) 优势

cpp 复制代码
// 1. 不阻塞调用者
void high_priority_thread(void)
{
    while (1) {
        // 处理实时任务...
        
        // 安排后台工作 - 不影响实时性
        k_work_reschedule(&bg_work, K_NO_WAIT);
        
        // 继续执行,无延迟
    }
}

// 2. 批量处理
void batch_processor(void)
{
    for (int i = 0; i < 100; i++) {
        // 快速安排所有工作
        k_work_reschedule(&work_items[i], K_NO_WAIT);
        // 立即继续
    }
}

2) 注意事项

cpp 复制代码
// 注意:避免安排过快导致队列溢出
void rapid_fire_work(void)
{
    for (int i = 0; i < 1000; i++) {
        // 可能使工作队列过载
        k_work_reschedule(&work, K_NO_WAIT);
    }
    // 考虑使用工作合并或速率限制
}

// 更好的做法:合并工作
struct batch_context {
    struct k_work_delayable work;
    int pending_count;
    int data[1000];
};

void batch_work_handler(struct k_work *work)
{
    struct batch_context *ctx = 
        CONTAINER_OF(work, struct batch_context, work.work);
    
    // 处理所有待处理数据
    for (int i = 0; i < ctx->pending_count; i++) {
        process_data(ctx->data[i]);
    }
    ctx->pending_count = 0;
}

void schedule_batch_work(struct batch_context *ctx, int new_data)
{
    ctx->data[ctx->pending_count++] = new_data;
    
    // 延迟安排,合并多次调用
    if (ctx->pending_count == 1) {
        k_work_reschedule(&ctx->work, K_MSEC(10));
    }
}

4.4 常见问题和解决方法

1) 如何知道工作何时完成?

cpp 复制代码
// 使用完成信号量
struct tracked_work {
    struct k_work_delayable dwork;
    struct k_sem done;
    bool completed;
};

void tracked_work_handler(struct k_work *work)
{
    struct tracked_work *tw = 
        CONTAINER_OF(k_work_delayable_from_work(work), 
                    struct tracked_work, dwork);
    
    do_work();
    
    tw->completed = true;
    k_sem_give(&tw->done);
}

// 等待完成(非阻塞检查)
bool is_work_done(struct tracked_work *tw)
{
    return tw->completed;
}

// 或阻塞等待
void wait_for_work(struct tracked_work *tw)
{
    k_sem_take(&tw->done, K_FOREVER);
}

2)如何取消安排的工作?

cpp 复制代码
// 取消延迟工作
int cancel_work(struct k_work_delayable *dwork)
{
    // 取消已安排但未执行的工作
    int ret = k_work_cancel_delayable(dwork);
    
    if (ret == 0) {
        printk("工作取消成功\n");
    } else if (ret == -EINPROGRESS) {
        printk("工作正在执行\n");
    }
    
    return ret;
}
相关推荐
ScilogyHunter8 小时前
Zephyr串口驱动开发及构建完全指南
驱动开发·uart·zephyr
ScilogyHunter10 小时前
Zephyr Hello World应用开发构建完全指南
zephyr·hello world
ScilogyHunter11 小时前
Zephyr Twister测试框架完全指南
zephyr·twister
ScilogyHunter1 天前
west init 命令详解
init·zephyr·west
ScilogyHunter1 天前
使用Kconfig配置Zephyr工程完全指南
kconfig·zephyr
ScilogyHunter2 天前
Zephyr设备树完全指南
zephyr
ScilogyHunter2 天前
Zephyr项目按需配置完全指南
zephyr
ScilogyHunter2 天前
Zephyr最简工程配置指南
zephyr
ScilogyHunter2 天前
Zephyr主仓库目录结构完全指南
zephyr
ScilogyHunter2 天前
Zephyr工程配置完全指南
zephyr