基于uCOS-II的任务池/线程池 模块

最新更新时间:2021-07-30来源: eefocus关键字:uCOS-II  线程池  模块

前言

线程池在软件开发中应用的很广泛,其很适合处理需要并行(并发)处理大量类似任务的情况。比如在web服务器端,需要为不同的socket(用户)同时提供服务,典型的模型就是为每个socket分别分配一个线程,一对一进行服务,这就涉及到大量的线程创建和销毁操作。当然,作为一个嵌入式软件,尤其还是以uCOS为操作系统的,一般是不会拿来作为高性能web服务器的。但是还是有很多时候会需要大量动态的线程。


线程池避免了创建和销毁线程带来的大量开销,使得软件效率得到了极大的提升。


uCOS-II中没有线程这个概念,而是使用了基于优先级的任务,同一时间只会运行所有准备好的任务中优先级最高的那个。但是有的时候又有使用类似线程池功能的需求,于是我基于uCOS的任务写了这个任务池模块,对线程池的功能进行简单地模拟。


模块简介

任务池模型

任务池的模型十分简单,模块内部有一个存放工作任务的消息队列(工作队列),你可以通过TP_WORKQ_IMP来选择工作队列的内部实现。在初始化时会创建TP_TASK_COUNT个任务(工人)来等待工作队列并从中依次提出工作来处理,用户则使用TP_AssignWork函数将每一个工作以及其附件传递给工作队列。


所以那些没法立即处理的工作任务会先缓存在工作队列中,等有工人空闲出来后就会继续处理。工作队列的大小由TP_WORKQ_SIZE决定。


注意,uCOS-II 是一个实时操作系统,而这个模块是基于uCOS-II的任务的。换句话说,只有所有准备好的任务中拥有最高优先级的任务才能运行,这也导致工作任务不保证会按照放入工作队列的顺序来完成。为了把这个池用得像一个真正的线程池:


工作任务最好是那些需要一段时间执行的,典型地比如那些需要与其他驱动、外设或任务交互的工作任务,这些工作任务常需要发出一个指令并等待执行结果。


当等待执行结果时,应该使用能进行任务切换(或说挂起当前任务)的API,比如OSTimeDlyHMSM、OSTimeDly、OSSemPend等。不要使用while(XXX){}来阻塞等待结果。


下面几张图表示出了任务池的整个工作流程(好萌的小人):




很形象吧,感觉不用多解释了。

而且当前实现提供的接口也很简单,就一个初始化以及一个布置任务。


Q&A

Q:为什么要提供那么多工作队列的实现,直接实现一种不就好了?

A:为了帮你省代码呀,比如,如果你在别的地方用到了uCOS-II的消息队列,那选择对应的实现,就相当于把这部分消息队列管理的代码省下来了,只有一点调用api的开销。但如果你专门为了任务池去启用了OS的这个功能,那其实很亏的。所以使用哪一种实现可以根据你项目的其他地方用到了哪个模块。像我个人比较喜欢全部用信号量,所以可能会倾向于选择 基于手写的工作队列结合uCOS-II的信号量 的那个实现。


Q:先布置的工作一定会经过工作队列么?

A:这取决于工作队列的具体实现,如果选择了那两个基于uCOS-II的消息队列的实现的话,如果有工人在pend工作队列,则下一个布置的任务不会放进任务池中,而是会直接交给工人,当然工人会不会立刻去处理还得看优先级的相对关系。而如果选择TP_WORKQ_IMP_QUEUE_OS_SEM这一项的话,则一定会先放进工作队列。


Q:工作任务要像uCOS的任务一样无限循环么?

A:工作任务不应该无限循环,否则工人就表现的像一个普通的uCOS任务一样,而任务池就会丢失一个工人。当然,如果你就是想从任务池中随便取几个任务来当普通任务用,那这符合你的要求。


Q:空闲的工人会立刻把工作队列中已有的工作提走么?

A:由于是基于uCOS-II任务实现的,所以实际上这个问题的答案取决于工人任务与其他已准备好的任务的相对优先级,比如,如果布置工作的任务的优先级低于等待中的工人的,那么它刚刚调用完api布置完任务甚至api还没返回,就会立刻切换到空闲工人的任务,然后工人就会提走工作并执行。而如果布置工作的任务的优先级最高的话,那他连续布置的n个工作都会无法立刻执行,直到其主动放弃cpu时间。


Q:先布置的工作一定会先执行么?

A:不一定,取决于取走工作的工人的相对优先级,极端情况下会出现先布置的任务最后执行的情况,但由于取走工作的顺序也是按照当前空闲工人的优先级的,所以整体上是先布置的先执行。详见上一章的说明。


Q:为什么工作队列的实现选项中还有内存管理这种东西?

A:消息队列只是暂存一个指针,还需要空间来存放相关信息(工作指针及附件),所以需要动态的内存分配。


Q:我用到了大量的uCOS-II内存管理模块,想将这个模块的内存管理与其他的合并?

A:工作队列实现选TP_WORKQ_IMP_OS_Q_PLUS_MEM,然后找到.c文件最后的MEMORY CONTROL IMPLEMENTATION那里进行对应修改。


代码

这里贴出代码:


/*

*********************************************************************************************************

*

*

*                                        Pool of Tasks for uCOS-II

*                                             uCOS-II 任务池

*

* File : TaskPool.h

* By   : Lin Shijun(http://blog.csdn.net/lin_strong)

* Date : 2018/08/08

* version: V1.0

* NOTE(s): This module implement a pool of tasks based on uCOS-II.

*          There is a message queues for works(workqueue) internal(choose the implementation by TP_WORKQ_IMP).

*        the module will initial TP_TASK_COUNT tasks(workers) to pend workqueue and pick the work one by one to 

*        process, and user call TP_AssignWork to pass work with its attachment to the workqueue.

*          So the works that can't be processed immediately will be buffered in the workqueue wating for 

*        processing.The size of the workqueue is defined by TP_WORKQ_SIZE. 

*          Note that, uCOS-II is a real-time OS, and this module is based on uCOS-II's tasks, which means

*        only the task which has highest priority among all ready tasks will get cpu time to run, and works

*        may not be processed as the order be put in the workqueue. To use the pool like a real "thread pool":

*          1. the works had better take a while to process, typically the work that interacts with other

*        drivers, peripherals or tasks, and need time wating for result of command;

*          2. the works should use APIs that enable task switching when wating for result of command, e.g

*        OSTimeDlyHMSM, OSTimeDly, OSSemPend and so on. Don't use while(XXX){} to pend result.

*          这个模块实现了基于uCOS-II的任务池。

*          模块内部有一个存放工作任务的消息队列(工作队列),你可以通过TP_WORKQ_IMP来选择工作队列的内部实现。

*        在初始化时会创建TP_TASK_COUNT个任务(工人)来等待工作队列并从中依次提出工作来处理,用户则使用

*        TP_AssignWork函数将每一个工作以及其附件传递给工作队列。

*          所以那些没法立即处理的工作任务会先缓存在工作队列中,等有工人空闲出来后就会继续处理。工作队列的

*        大小由TP_WORKQ_SIZE决定。

*          注意,uCOS-II 是一个实时操作系统,而这个模块是基于uCOS-II的任务的。换句话说,只有所有准备好的任务中

*        拥有最高优先级的任务才能运行,这也导致工作任务不保证会按照放入工作队列的顺序来完成。为了把这个池用得

*        像一个真正的线程池:

*          1. 工作任务最好是那些需要一段时间执行的,典型地比如那些需要与其他驱动、外设或任务交互的工作任务,

*        这些工作任务常需要发出一个指令并等待执行结果。

*          2. 当等待执行结果时,应该使用能进行任务切换(或说挂起当前任务)的API,比如OSTimeDlyHMSM、OSTimeDly、

*        OSSemPend等。不要使用while(XXX){}来阻塞等待结果。

*          

*          the work shouldn't has infinite loop, or the worker will act like a normol uCOS-II task, and the

*        task pool will lose the worker.

*          工作任务不应该无限循环,否则工人就表现的像一个普通的uCOS任务一样,而任务池就会丢失一个工人。

* History : 2018/08/08   the original version of TaskPool.

*********************************************************************************************************

*/



#ifndef   TASK_POOL_H

#define   TASK_POOL_H

/*

*********************************************************************************************************

*                                       INCLUDE

*********************************************************************************************************

*/

// based on ucos_ii

#include "ucos_ii.h"


/*

*********************************************************************************************************

*                                       MISCELLANEOUS

*********************************************************************************************************

*/


#ifndef  FALSE

#define  FALSE    0

#endif


#ifndef  TRUE

#define  TRUE     1

#endif


/*

*********************************************************************************************************

*                                        CONSTANTS     常量

*********************************************************************************************************

*/

#define TP_ERR_NONE                        0u


#define TP_ERR_POINTER_NULL                1u

#define TP_ERR_TASK_INIT                   2u

#define TP_ERR_WORKQ_INIT                  3u

//#define TP_ERR_MEM_INIT                    4u


#define TP_ERR_WORKQ_FULL                  5u

#define TP_ERR_MEMORY                      6u


#define TP_ERR_UNKNOWN                     254u


// choose the implementation of internal workqueue 可选的工作队列内部实现方式

#define TP_WORKQ_IMP_OS_Q_PLUS_MEM   1   // based on uCOS-II's Message Queue and memory management

                                         // 基于uCOS-II的消息队列和内存管理

#define TP_WORKQ_IMP_OS_Q_STD_MEM    2   // based on uCOS-II's Message Queue and stdlib's memory management

                                         // 基于uCOS-II的消息队列和标准库的内存管理

#define TP_WORKQ_IMP_QUEUE_OS_SEM    3   // based on manually queue and uCOS-II's semaphore

                                         // 基于手写的工作队列结合uCOS-II的信号量

/*

*********************************************************************************************************

*                                       CONFIGURATION  配置

*********************************************************************************************************

*/


// NOTE: the init procedure will create tasks, whose priority from TP_TASK_PRIO_START to 

//      (TP_TASK_PRIO_START + TP_TASK_COUNT - 1), and let them work in the pool

// 注意:在初始化时,初始化函数会创建优先级从TP_TASK_PRIO_START开始的TP_TASK_COUNT个任务放入任务池,

//       用户需保证没有优先级冲突

#define TP_TASK_PRIO_START      20       // the priority of the first task in the pool

                                         // 任务池中第一任务的优先级

#define TP_TASK_COUNT           4        // the number of tasks in the pool           

                                         // 任务池中任务数

#define TP_TASK_STACK_SIZE      300      // the size of stacks of each tasks in the pool 

[1] [2] [3] [4]
关键字:uCOS-II  线程池  模块 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic543349.html

上一篇:Motorola S-records(S19)解析模块
下一篇:MC9S12XEP100的ATD模块(ADC12B16CV1)

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

UCOS-II在MC9S12XS128上的移植
操作系统是一种与硬件为基础的系统软件,硬件系统不一样,那在其上面运行的操作系统也会不一样。一般来说,操作系统是与芯片相关联的。要在某型号的芯片上运行操作系统,那得在操作系统内核的基础上编写一些与芯片相关的驱动程序,并对内核的配置文件做相应的改动,然后在编译器上编译,链接,然后下载到芯片上。这个过程就是所谓的操作系统的移植了。UCOS-II是个开源的也就是原代码公开的内核,可以免费用于非商业的各种运用中。其原代码可以在http://micrium.com/page/products/rtos/os-ii上找到。上面有好多在某些芯片上移植成功的实例,如果芯片型号对应,则可以下载下来直接用。这样就可以省去好多移植的工作,而直接在上面编写
发表于 2021-08-12
ucos-ii在MC9S12XDP512上的移植
      搞了几天,总算把ucos-ii移植到MC9S12XDP512上了。做个简短的笔记。      ucos-ii版本:2.52, 编译器:Freescale CodeWarrior5.9 芯片:MC9S12XDP512      移植步骤:      1.  根据向导建立新的工程,芯片选择MC9S12XDP512,其余默认配置;      2.  将ucos-ii通用源文件复制到工程的Sources目录下下:OS_CORE.C,OS_DBG.C,OS
发表于 2021-08-11
MC9S12XEP100 SCI(UART)驱动程序2 - 基于uCOS-II
首先先发一个自己封装的MC9S12XEP100的SCI模块(也就是UART模块)的驱动。这些代码参考了 Li Yuan http://blog.csdn.net/liyuanbhu/article/details/7764851 的代码,整个代码风格是按照uCOS-II操作系统源码的风格来写的,在此表示感谢。目前还不是特别完整完善,但基本使用是没有问题了。在上一章中已经发了硬件驱动部分,这里发下基于uCOS-II嵌入式操作系统的驱动部分以及顺便说下怎么用。首先要记得到上一章中把两个文件存了,顺便还要把.h文件中的SCI_UCOS_MODULE_ENABLE 后面改为 TRUE 以开启RTOS(嵌入式操作系统)驱动部分。目前这个版本
发表于 2021-07-26
UCOS-II中OS_CPU_IRQ_ISR移植过程分析
简介:在讨论ARM的移植过程中,我觉得首先应该搞清楚每一种情况下CPU的工作模式,同时搞清楚寄存器的特殊性,同时搞清楚中断处理的一般过程。在uc/os-II的移植过程中存在一个通用的irq中断处理函数,其中的实现过程如下:OS_CPU_IRQ_ISRSTMFD SP!, {R1-R3} ; We will use R1-R3 as temporary registersMOV R1, SPADD SP, SP, #12 ;Adjust IRQ stack pointerSUB R2, LR, #4 ;Adjust PC for return address to taskMRS R3, SPSR ; Copy SPSR (Task
发表于 2021-07-05
ucos ii 移植到STM32f103ze上
简介:在移植UCOS时,需要编写的函数文件有includes.h、os_cpu.c、os_cpu_a.asm、os_cpu.h、需要配置的文件有os_cgf.h、中断和启动代码。采用别人移植好的代码。即所需函数已写好。准备工作:1、ucos ii源码2、stm32库步骤:1、建工程。工程目录为:2、配置ucos ii在os_cfg.h中配置相关功能3、修改相关函数ucos ii需要一个定时器,在stm32中采用systick定时器,因此需要配置systick定时器void SysTick_Configuration(void){//关计数SysTick_CounterCmd(SysTick_Counter_Disable
发表于 2021-07-05
<font color='red'>ucos</font> <font color='red'>ii</font> 移植到STM32f103ze上
STM32CubeMx之资源(线程,队列,内存)管理
由于可能创建很多个线程,线程互相通信,因此,我们将线程ID统一存储在一个结构体中,进行管理。资源管理结构体如下:typedef struct resource{    uint8_t initialized;    uint8_t id;        osThreadId          led_thread;    uint8_t             led_initialized; 
发表于 2021-06-16
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved