查看: 983|回复: 0

[技术交流] Alios之工作队列(work queue)

[复制链接]

74

主题

169

帖子

573

积分

利尔达员工

Rank: 9Rank: 9Rank: 9

积分
573
发表于 2020-4-14 10:38:23 | 显示全部楼层 |阅读模式
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的结构体定义:
  1. typedef struct{
  2. klist_t                 workqueue_node;  /*挂载workqueue列表*/
  3. klist_t                 work_list; /*workqueue下挂载的work列表*/
  4. kwork_t             *work_current;  /*正在被处理的work*/
  5. const name_t    *name;
  6. ktask_t               worker;  /*workqueue关联并创建的任务*/
  7. ksem_t               sem; /*workqueue创建并阻塞执行的信号量*/
  8. }kworkqueue_t;
复制代码

(1)work queue的初始化
初始化函数:void workqueue_init(void)
该函数首先初始化名为g_workqueue_list_head的工作队列链表,该链表将挂接所有的workqueue。同时还通过krhino_workqueue_create接口创建一个工作队列g_workqueue_default。
(2)work queue的创建
函数原型:
  1. kstart_t krhino_workqueue_create(
  2. kworkqueue_t *workqueue,
  3. const name_t *name,
  4. uint8_t pri,
  5. cpu_stack_t *stack_buf,
  6. size_t stack_size
  7. )
复制代码
参数中有优先级、栈起始和栈大小,这三个参数用来在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)

回复

使用道具 举报

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

本版积分规则

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