查看: 853|回复: 0

[技术交流] ALiOS工作队列机制简述

[复制链接]

74

主题

169

帖子

573

积分

利尔达员工

Rank: 9Rank: 9Rank: 9

积分
573
发表于 2019-9-6 09:50:27 | 显示全部楼层 |阅读模式
1、前言

在一个操作系统中,如果要进行一项工作处理,往往需要创建一个任务来加入内核的调度机制。一个任务对应一个处理函数,如果要进行不同的任务处理,则需要创建多个任务。任务作为CPU调度的基础单元,数量越大,则调度成本越高。work queue机制简化了基本的任务创建和处理机制,一个work实体对应一个实体task的处理,work queue下面可以挂接多个work实体,每一个work实体都能对应不同的处理接口,即用户只需要创建一个work queue,就可以完成多个挂接不同处理函数的work queue。

在某些实时性要求较高的任务中,需要进行比较繁重钩子处理时(hook)处理时,可以将其处理函数挂在work queue中,其执行过程将位于work queue的上下文,而不会占用原有任务的处理资源。

另外,work queue还提供了work的延时处理机制,用户可以选择立即执行或是延时处理。

由此可见,在需要创建大量实时性要求不高的任务时,可以使用work queue来统一调度;或者将任务中实时性要求不高的部分处理延后到work queue中处理。如果需要设置延后处理,则需要使用work机制,即用户在创建work时需要指定work的延迟执行时间。work机制不支持周期work的处理。

2、work queue机制原理

work queue的处理依赖于task。一个work queue会创建关联其对应的task,一个work queue会挂载多个work处理,每个work处理对应一个处理函数。当work queue得到调度,即其关联的task得到运行,在每次task的调度期间,都会从work queue中按照先后顺序取出一个work来进行处理。下面是work queue的基本数据结构。

参考kworkqueue_t的结构体定义:


typedef struct{

klist_t                 workqueue_node;  /*挂载workqueue列表*/

klist_t                 work_list; /*workqueue下挂载的work列表*/

kwork_t             *work_current;  /*正在被处理的work*/

const name_t    *name;

ktask_t               worker;  /*workqueue关联并创建的任务*/

ksem_t               sem; /*workqueue创建并阻塞执行的信号量*/

}kworkqueue_t;


(1)work queue的初始化

初始化函数:void workqueue_init(void)

该函数首先初始化名为g_workqueue_list_head的工作队列链表,该链表将挂接所有的workqueue。同时还通过krhino_workqueue_create接口创建一个工作队列g_workqueue_default。

(2)work queue的创建

函数原型:


kstart_t krhino_workqueue_create(

kworkqueue_t *workqueue,

const name_t *name,

uint8_t pri,

cpu_stack_t *stack_buf,

size_t stack_size

)


参数中有优先级、栈起始和栈大小,这三个参数用来在work queue内部创建对应的调度任务。另外,该函数还创建了一个信号量(sem),初始信号值为0。

该任务将会循环获取此信号量,当获取不到时,则该任务永久阻塞;一旦获取信号量,就从work queue中取出一个work来进行处理。

3、work的创建与触发

(1)work的创建

函数原型:kstart_t krhino_work_init(kwork_t *work,work_handle_t handle,void *arg,tick_t dly)

此函数用例创建一个work单元,参数包含处理函数钩子,处理参数,dly表示work是否需要延时。

(2)work的触发

函数原型:kstart_t krhino_work_run(kworkqueue_t *workqueue,kwork_t *work)

该函数的目的是将某个work推送到一个work queue中,并通过释放workqueue阻塞的信号量来触发work的调度处理。每释放一次信号量,处理一个work。

(3)work queue资源释放

work queue的资源释放:kstart_t krhino_workqueue_del(kworkqueue_t *workqueue)

该函数首先判断当前work queue中是否存在待处理的work,如果存在,则释放失败;释放资源包括work queue关联任务、信号量,并将自身从g_workqueue_list_head队列中删除。

work的资源释放:kstart_t krhino_work_cancel(kwork_t  *work)



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表