全部文档
OneOS简介 硬件支持 编译构造工具 API参考文档 高级语言 用户编程手册 应用笔记 FAQ

工作队列


简介

工作队列(workqueue)是对任务封装的一种用于处理各种工作项(work)的机制,由于处理的对象是用链表连接起来的一个个工作项,在封装的任务中被依次取出来一个个处理,就像队列依次处理一样,所以称为工作队列。

从原理上简单来讲,创建一个工作队列,实际上会创建一个任务;向工作队列上提交工作项,实际上会向该工作队列的链表上添加工作项,注册时可以选择延时或者不延时执行;而工作队列所对应的任务一旦检测到链表上有工作项需要执行,则会调用对应工作项的回调函数。

对于一些简单的功能函数或者不需要不断循环处理的,如果单独创建一个任务来处理就显得有点浪费,此时选择工作队列会更合适。另外工作队列是在任务环境中执行的,可以睡眠,所以针对中断触发的某些事情,也可以把其中某些对时间要求不高的部分放到工作队列里面去处理。

本操作系统提供的工作队列有两种接口。第一种接口,用户可以创建自己的工作队列,自行决定栈大小和任务优先级,然后把需要的工作项提交到工作队列上;另外一种接口,用户不用创建工作队列,而是直接把工作项提交到系统创建的工作队列上。


重要定义及数据结构

结构体

struct os_workqueue
{
    os_list_node_t  pending_list_head;    
    os_list_node_t  delaying_list_head;  

    os_work_t      *work_current;           /* Work in progress on workqueue */
    os_task_t      *process_task;           /* Task on the workqueue to execute work */
    os_sem_t        process_sem;            /* Semaphore for synchronization */                                   

    os_bool_t       destroy;                /* Used to flag whether the workqueue is destroyed */             
};
struct os_workqueue参数 说明
pending_list_head 工作队列上即将执行的工作项链表头
delaying_list_head 工作队列上延时执行的工作项链表头
work_current 工作队列上正在执行的工作项
process_task 工作队列对应的任务
process_sem 信号量,用来通知工作队列的任务有工作项需要处理
destroy 标志,表明该工作队列正在销毁
struct os_work
{
    os_list_node_t      list;

    void                (*func)(struct os_work *work, void *data);
    void                *data;

    void                (*cleanup)(struct os_work *work);

    os_work_stage_t     stage;
    os_uint16_t         ref_count;

    os_timer_t          timer;
    os_sem_t            sem;

    struct os_workqueue *workqueue;
};
struct os_work参数 说明
list 工作项链表节点,用于挂到工作队列的链表上
func 使用者注册的工作项函数
data 使用者注册的工作项函数的参数
cleanup 使用者注册的清除函数
stage 工作项的状态
ref_count 工作项的引用计数
timer 定时器,用于延时处理的工作项
sem 信号量,用于等待工作项完成

API列表

接口 说明
os_workqueue_create 创建工作队列
os_workqueue_destroy 销毁工作队列
os_workqueue_submit_work 向工作队列提交工作项
os_workqueue_cancel_work 取消工作队列上的指定工作项,若该工作项已经开始运行,会立即返回OS_EBUSY错误码
os_workqueue_cancel_work_sync 以同步方式取消工作队列上的指定工作项,若该工作项已经开始运行,会等待工作项执行完后再返回
os_workqueue_cancel_all_work 取消工作队列上的所有未执行的工作项(包括正在排队的和延时执行的),正在执行的工作项不能取消
os_work_init 初始化工作项
os_work_deinit 反初始化工作项
os_submit_work 向系统维护的工作队列提交工作项
os_cancel_work 取消系统工作队列上的指定工作项,若该工作项已经开始运行,会立即返回OS_EBUSY错误码
os_cancel_work_sync 以同步方式取消系统工作队列上的工作项,如果该工作项已经开始运行,会等待工作项执行完后再返回
os_cancel_all_work 取消系统工作队列上的所有未执行的工作项(包括正在排队的和延时执行的),正在执行的工作项不能取消

os_workqueue_create

该函数用于创建工作队列,内部会创建一个对应的任务,函数原型如下:

os_workqueue_t *os_workqueue_create(const char *name, os_uint32_t stack_size, os_uint8_t priority);
参数 说明
name 工作队列的名字
stack_size 工作队列对应任务的栈大小
priority 工作队列对应任务的优先级
返回 说明
非OS_NULL 创建成功,返回工作队列句柄
OS_NULL 创建失败

os_workqueue_destroy

该函数用于销毁工作队列,函数原型如下:

os_err_t os_workqueue_destroy(os_workqueue_t *queue);
参数 说明
queue 工作队列句柄
返回 说明
OS_EOK 销毁成功

os_workqueue_submit_work

该函数用于向工作队列上提交工作项,可指定延时时间,函数原型如下:

os_err_t os_workqueue_submit_work(os_workqueue_t *queue, os_work_t *work, os_tick_t delay_time);
参数 说明
queue 工作队列句柄
work 待提交的工作项,该工作项需提前用os_work_init()初始化
delay_time 延时时间,可取值范围0~(OS_TICK_MAX / 2 - 1)
返回 说明
OS_EOK 提交成功
OS_EBUSY 该工作项之前已被提交,但还未执行完成

os_workqueue_cancel_work

该函数用于取消工作队列上的指定工作项,若该工作项已开始执行,则返回OS_EBUSY,函数原型如下:

os_err_t os_workqueue_cancel_work(os_workqueue_t *queue, os_work_t *work);
参数 说明
queue 工作队列句柄
work 待取消的工作项
返回 说明
OS_EOK 取消成功
OS_EBUSY 取消失败,该工作项正在执行
OS_ERROR 其它错误

os_workqueue_cancel_work_sync

该函数用于以同步方式取消工作队列上的指定工作项,若该工作项已开始执行,则会等待其执行完成,函数原型如下:

os_err_t os_workqueue_cancel_work_sync(os_workqueue_t *queue, os_work_t *work);
参数 说明
queue 工作队列句柄
work 待取消的工作项
返回 说明
OS_EOK 取消成功
OS_ERROR 取消错误

os_workqueue_cancel_all_work

该函数用于取消工作队列上的所有工作项(包括正在排队的和延时执行的),正在执行的工作项不能取消,函数原型如下:

void os_workqueue_cancel_all_work(os_workqueue_t *queue);
参数 说明
queue 工作队列句柄
返回 说明

os_work_init

该函数用于初始化工作项,函数原型如下:

void os_work_init(os_work_t *work, void (*func)(struct os_work *work, void *data), void *data);
参数 说明
work 工作项句柄,由使用者提供
func 工作项函数
data 工作项函数的参数
返回 说明

os_work_deinit

该函数用于反初始化工作项,可以指定清除函数,函数原型如下:

void os_work_deinit(os_work_t *work, void (*cleanup)(os_work_t *work));
参数 说明
work 工作项句柄
cleanup 清除函数,使用者可以通过注册此函数,在反初始化工作项后执行一些清理的操作
返回 说明

os_submit_work

该函数向系统工作队列提交工作项(系统工作队列默认任务的栈为OS_SYSTEM_WORKQUEUE_STACK_SIZE,优先级为OS_SYSTEM_WORKQUEUE_PRIORITY),函数原型如下:

os_err_t os_submit_work(os_work_t *work, os_tick_t time);
参数 说明
work 向系统工作队列提交的工作项句柄,该工作项需提前使用os_work_init()初始化
time 延时时间,可取值范围0~(OS_TICK_MAX / 2 - 1)
返回 说明
OS_EOK 提交成功
OS_EBUSY 该工作项之前已被提交,但还未执行完成

os_cancel_work

该函数用于取消系统工作队列上指定的工作项,若该工作项已开始运行,则返回OS_EBUSY,函数原型如下:

os_err_t os_cancel_work(os_work_t *work);
参数 说明
work 待取消的工作项句柄
返回 说明
OS_EOK 取消成功
OS_EBUSY 取消失败,该工作项正在执行
OS_ERROR 其它错误

os_cancel_work_sync

该函数用于以同步方式取消系统工作队列上的指定工作项,若该工作项已开始执行,则会等待其执行完成,函数原型如下:

os_err_t os_cancel_work_sync(os_work_t *work);
参数 说明
work 待取消的工作项句柄
返回 说明
OS_EOK 取消成功
OS_ERROR 取消错误

os_cancel_all_work

该函数用于取消系统工作队列上的所有工作项(包括正在排队的和延时执行的),正在执行的工作项不能取消,函数原型如下:

void os_cancel_all_work(void);

使用示例

自己创建工作队列使用示例

本例创建了自己的工作队列,然后在任务1中周期性的提交工作项到该工作队列,在任务2中分别提交了一个需要延时的工作项和不需要延时的工作项到该工作队列

#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <os_task.h>
#include <shell.h>
#include <os_workqueue.h>

#define TEST_TAG            "TEST"
#define TASK_STACK_SIZE     1024
#define TASK1_PRIORITY      15
#define TASK2_PRIORITY      16
#define TASK_WQ_PRIORITY    10
#define TASK_TIMESLICE      10

static os_workqueue_t *workqueue_test;
static os_work_t work1;
static os_work_t work2;
static os_work_t work3;

void work1_func(os_work_t *work, void *data)
{
    LOG_W(TEST_TAG, "work1_func, data:%d", *(os_uint32_t *)data);
}

void work2_func(os_work_t *work, void *data)
{
    LOG_W(TEST_TAG, "work2_func");
}

void work3_func(os_work_t *work, void *data)
{
    LOG_W(TEST_TAG, "work3_func");
}

void task1_entry(void *para)
{
    os_uint32_t data = 0;

    os_work_init(&work1, work1_func, &data);
    while(1)
    {
        data++;        
        LOG_W(TEST_TAG, "task1 submit work1");
        while(OS_EBUSY == os_workqueue_submit_work(workqueue_test, &work1, 0))
        {
            os_task_sleep(10);
        }
        os_task_sleep(500);
    }
}

void task2_entry(void *para)
{
    os_tick_t delay_time = 1000;

    os_work_init(&work2, work2_func, OS_NULL);
    LOG_W(TEST_TAG, "task2 submit work2, delay_time:%d", delay_time);
    if(OS_EOK != os_workqueue_submit_work(workqueue_test, &work2, delay_time))
    {
        LOG_W(TEST_TAG, "task2 submit work2 ERR");
    }

    os_task_sleep(500);

    delay_time = 0;
    os_work_init(&work3, work3_func, OS_NULL);
    LOG_W(TEST_TAG, "task2 submit work3, delay_time:%d", delay_time);
    if(OS_EOK != os_workqueue_submit_work(workqueue_test, &work3, delay_time))
    {
        LOG_W(TEST_TAG, "task2 submit work3 ERR");
    }
}

void workqueue_sample(void)
{
    os_task_t *task1 = OS_NULL;
    os_task_t *task2 = OS_NULL;

    workqueue_test = os_workqueue_create("workqueue", TASK_STACK_SIZE, TASK_WQ_PRIORITY);
    if (!workqueue_test)
    {
        LOG_W(TEST_TAG, "workqueue_sample workqueue create ERR");
        return;
    }

    task1 = os_task_create("task1", 
                           task1_entry, 
                           OS_NULL, 
                           TASK_STACK_SIZE, 
                           TASK1_PRIORITY, 
                           TASK_TIMESLICE);
    if (task1)
    {        
        LOG_W(TEST_TAG, "workqueue_sample startup task1");
        os_task_startup(task1);
    }

    task2 = os_task_create("task2", 
                           task2_entry, 
                           OS_NULL, 
                           TASK_STACK_SIZE, 
                           TASK2_PRIORITY, 
                           TASK_TIMESLICE);
    if (task2)
    {        
        LOG_W(TEST_TAG, "workqueue_sample startup task2");
        os_task_startup(task2);
    }
}

SH_CMD_EXPORT(test_workqueue, workqueue_sample, "test workqueue");

运行结果如下:

sh />test_workqueue
W/TEST: workqueue_sample startup task1
W/TEST: task1 submit work1
W/TEST: work1_func, data:1
W/TEST: workqueue_sample startup task2
W/TEST: task2 submit work2, delay_time:1000
W/TEST: task1 submit work1
W/TEST: work1_func, data:2
W/TEST: task2 submit work3, delay_time:0
W/TEST: work3_func
W/TEST: task1 submit work1
W/TEST: work2_func
W/TEST: work1_func, data:3
W/TEST: task1 submit work1
W/TEST: work1_func, data:4
W/TEST: task1 submit work1
W/TEST: work1_func, data:5

系统工作队列使用示例

本例使用系统工作队列,不创建自己的工作队列,用另外一套接口,达到和上面示例中一样的效果,使用起来更简单方便

#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <os_task.h>
#include <shell.h>
#include <os_workqueue.h>

#define TEST_TAG            "TEST"
#define TASK_STACK_SIZE     1024
#define TASK1_PRIORITY      15
#define TASK2_PRIORITY      16
#define TASK_TIMESLICE      10

static os_work_t work1;
static os_work_t work2;
static os_work_t work3;

void work1_func(os_work_t *work, void *data)
{
    LOG_W(TEST_TAG, "work1_func, data:%d", *(os_uint32_t *)data);
}

void work2_func(os_work_t *work, void *data)
{
    LOG_W(TEST_TAG, "work2_func");
}

void work3_func(os_work_t *work, void *data)
{
    LOG_W(TEST_TAG, "work3_func");
}

void task1_entry(void *para)
{
    os_uint32_t data = 0;

    os_work_init(&work1, work1_func, &data);
    while(1)
    {
        data++;        
        LOG_W(TEST_TAG, "task1 submit work1");
        while(OS_EBUSY == os_submit_work(&work1, 0))
        {
            os_task_sleep(10);
        }
        os_task_sleep(500);
    }
}

void task2_entry(void *para)
{
    os_tick_t delay_time = 1000;

    os_work_init(&work2, work2_func, OS_NULL);
    LOG_W(TEST_TAG, "task2 submit work2, delay_time:%d", delay_time);
    if(OS_EOK != os_submit_work(&work2, delay_time))
    {
        LOG_W(TEST_TAG, "task2 submit work2 ERR");
    }

    os_task_sleep(500);

    delay_time = 0;
    os_work_init(&work3, work3_func, OS_NULL);
    LOG_W(TEST_TAG, "task2 submit work3, delay_time:%d", delay_time);
    if(OS_EOK != os_submit_work(&work3, delay_time))
    {
        LOG_W(TEST_TAG, "task2 submit work3 ERR");
    }
}

void sys_workqueue_sample(void)
{
    os_task_t *task1 = OS_NULL;
    os_task_t *task2 = OS_NULL;

    task1 = os_task_create("task1", 
                           task1_entry, 
                           OS_NULL, 
                           TASK_STACK_SIZE, 
                           TASK1_PRIORITY, 
                           TASK_TIMESLICE);
    if (task1)
    {        
        LOG_W(TEST_TAG, "sys_workqueue_sample startup task1");
        os_task_startup(task1);
    }

    task2 = os_task_create("task2", 
                           task2_entry, 
                           OS_NULL, 
                           TASK_STACK_SIZE, 
                           TASK2_PRIORITY, 
                           TASK_TIMESLICE);
    if (task2)
    {        
        LOG_W(TEST_TAG, "sys_workqueue_sample startup task2");
        os_task_startup(task2);
    }
}

SH_CMD_EXPORT(test_sys_workqueue, sys_workqueue_sample, "test system workqueue");

运行结果如下:

sh />test_sys_workqueue
W/TEST: sys_workqueue_sample startup task1
W/TEST: task1 submit work1
W/TEST: work1_func, data:1
W/TEST: sys_workqueue_sample startup task2
W/TEST: task2 submit work2, delay_time:1000
W/TEST: task1 submit work1
W/TEST: work1_func, data:2
W/TEST: task2 submit work3, delay_time:0
W/TEST: work3_func
W/TEST: task1 submit work1
W/TEST: work2_func
W/TEST: work1_func, data:3
W/TEST: task1 submit work1
W/TEST: work1_func, data:4
W/TEST: task1 submit work1
W/TEST: work1_func, data:5

results matching ""

    No results matching ""

    返回顶部