您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 信息化管理 > FreeRTOS任务管理分析
FreeRTOS任务管理分析freertos是一个轻量级的rtos,它目前实现了一个微内核,并且port到arm7,avr,pic18,coldfire等众多处理器上;目前已经在rtos的市场上占有不少的份额。它当然不是一个与vxworks之类的rtos竞争的操作系统,它的目标在于低性能小RAM的处理器上。整个系统只有3个文件,外加上port的和处理器相关的两个文件,实现是很简洁的。与ucosii不同,它是free的,ucosii不是free的,虽然它的代码是公开的。FreeRTOS提供的功能包括:任务管理、时间管理、信号量、消息队列、内存管理。FreeRTOS内核支持优先级调度算法,每个任务可根据重要程度的不同被赋予一定的优先级,CPU总是让处于就绪态的、优先级最高的任务先运行。FreeRT0S内核同时支持轮换调度算法,系统允许不同的任务使用相同的优先级,在没有更高优先级任务就绪的情况下,同一优先级的任务共享CPU的使用时间。这一点是和ucosii不同的。另外一点不同是freertos既可以配置为可抢占内核也可以配置为不可抢占内核。当FreeRTOS被设置为可剥夺型内核时,处于就绪态的高优先级任务能剥夺低优先级任务的CPU使用权,这样可保证系统满足实时性的要求;当FreeRTOS被设置为不可剥夺型内核时,处于就绪态的高优先级任务只有等当前运行任务主动释放CPU的使用权后才能获得运行,这样可提高CPU的运行效率。这篇文章是以freertosv5.0版本的代码为例子分析下它的任务管理方面的实现。时间关系可能没有太多时间写的很详细了。1.链表管理freertos里面的任务管理,queue,semaphore管理等都借助于双向链表,它定义了个通用的数据结构structxLIST_ITEM{portTickTypexItemValue;//链表节点的数据项,通常用在任务延时,表示//一个任务延时的节拍数volatilestructxLIST_ITEM*pxNext;//通过这两个成员变量将所有节点volatilestructxLIST_ITEM*pxPrevious;//链接成双向链表void*pvOwner;//指向该item的所有者,通常是任务控制块void*pvContainer;//指向此链表结点所在的链表};这个数据结构定义了一个通用的链表节点;下面的数据结构定义了一个双向链表typedefstructxLIST{volatileunsignedportBASE_TYPEuxNumberOfItems;//表示该链表中节点的数目volatilexListItem*pxIndex;//用于遍历链表,指向上次访问的节点volatilexMiniListItemxListEnd;//链表尾结点}xList;而下面这个数据结构用在xList中,只是为了标记一个链表的尾,是一个markerstructxMINI_LIST_ITEM{portTickTypexItemValue;volatilestructxLIST_ITEM*pxNext;volatilestructxLIST_ITEM*pxPrevious;};typedefstructxMINI_LIST_ITEMxMiniListItem;对于链表的操作也定义了一系列的函数和宏,在list.c文件中。如初始化个链表,吧一个节点插入链表等。初始化链表:voidvListInitialise(xList*pxList){pxList-pxIndex=(xListItem*)&(pxList-xListEnd);pxList-xListEnd.xItemValue=portMAX_DELAY;pxList-xListEnd.pxNext=(xListItem*)&(pxList-xListEnd);pxList-xListEnd.pxPrevious=(xListItem*)&(pxList-xListEnd);pxList-uxNumberOfItems=0;}把一个节点插入到链表尾部:voidvListInsertEnd(xList*pxList,xListItem*pxNewListItem){volatilexListItem*pxIndex;pxIndex=pxList-pxIndex;pxNewListItem-pxNext=pxIndex-pxNext;pxNewListItem-pxPrevious=pxList-pxIndex;pxIndex-pxNext-pxPrevious=(volatilexListItem*)pxNewListItem;pxIndex-pxNext=(volatilexListItem*)pxNewListItem;pxList-pxIndex=(volatilexListItem*)pxNewListItem;pxNewListItem-pvContainer=(void*)pxList;(pxList-uxNumberOfItems)++;}这些就不多说了。2.任务控制块typedefstructtskTaskControlBlock{volatileportSTACK_TYPE*pxTopOfStack;//指向堆栈顶xListItemxGenericListItem;//通过它将任务连入就绪链表或者延时链表或者挂起链表中xListItemxEventListItem;//通过它把任务连入事件等待链表unsignedportBASE_TYPEuxPriority;//优先级portSTACK_TYPE*pxStack;//指向堆栈起始位置signedportCHARpcTaskName[configMAX_TASK_NAME_LEN];#if(portCRITICAL_NESTING_IN_TCB==1)unsignedportBASE_TYPEuxCriticalNesting;#endif#if(configUSE_TRACE_FACILITY==1)unsignedportBASE_TYPEuxTCBNumber;//用于trace,debug时候提供方便#endif#if(configUSE_MUTEXES==1)unsignedportBASE_TYPEuxBasePriority;//当用mutex发生优先级反转时用#endif#if(configUSE_APPLICATION_TASK_TAG==1)pdTASK_HOOK_CODEpxTaskTag;#endif}tskTCB;其中uxBasePriority用于解决优先级反转,freertos采用优先级继承的办法解决这个问题,在继承时,将任务原先的优先级保存在这个成员中,将来再从这里恢复任务的优先级。3.系统全局变量freertos将任务根据他们的状态分成几个链表。所有就绪状态的任务根据任务优先级加到对应的就绪链表中。系统为每个优先级定义了一个xList。如下:staticxListpxReadyTasksLists[configMAX_PRIORITIES];此外,所有延时的任务加入到两个延时链表之一。staticxListxDelayedTaskList1;staticxListxDelayedTaskList2;还定义了两个指向延时链表的指针:staticxList*volatilepxDelayedTaskList;staticxList*volatilepxOverflowDelayedTaskList;freertos弄出两个延时链表是因为它的延时任务管理的需要。freertos根据任务延时时间的长短按序将任务插入这两个链表之一。在插入前先把任务将要延时的xTicksToDelay数加上系统当前tick数,这样得到了一个任务延时duetime(到期时间)的绝对数值。但是有可能这个相加操作会导致溢出,如果溢出则加入到pxOverflowDelayedTaskList指向的那个链表,否则加入pxDelayedTaskList指向的链表。freertos还定义了个pending链表:staticxListxPendingReadyList;这个链表用在调度器被lock(就是禁止调度了)的时期,如果一个任务从非就绪状态变为就绪状态,它不直接加到就绪链表中,而是加到这个pending链表中。等调度器重新启动(unlock)的时候再检查这个链表,把里面的任务加到就绪链表中staticvolatilexListxTasksWaitingTermination;staticvolatileunsignedportBASE_TYPEuxTasksDeleted=(unsignedportBASE_TYPE)0;一个任务被删除的时候加入到xTasksWaitingTermination链表中,uxTasksDeleted跟中系统中有多少任务被删除(即加到xTasksWaitingTermination链表的任务数目).staticxListxSuspendedTaskList;这个链表记录着所有被xTaskSuspend挂起的任务,注意这不是那些等待信号量的任务。staticvolatileunsignedportBASE_TYPEuxCurrentNumberOfTasks;记录了当前系统任务的数目staticvolatileportTickTypexTickCount;是自启动以来系统运行的ticks数staticunsignedportBASE_TYPEuxTopUsedPriority;记录当前系统中被使用的最高优先级,staticvolatileunsignedportBASE_TYPEuxTopReadyPriority;记录当前系统中处于就绪状态的最高优先级。staticvolatilesignedportBASE_TYPExSchedulerRunning;表示当前调度器是否在运行,也即内核是否启动了4.任务管理freertos与ucosii不同,它的任务控制块并不是静态分配的,而是在创建任务的时候动态分配。另外,freertos的优先级是优先级数越大优先级越高,和ucosii正好相反。任务控制块中也没有任务状态的成员变量,这是因为freertos中的任务总是根据他们的状态连入对应的链表,没有必要在任务控制块中维护一个状态。此外freertos对任务的数量没有限制,而且同一个优先级可以有多个任务。先看任务创建:signedportBASE_TYPExTaskCreate(pdTASK_CODEpvTaskCode,constsignedportCHAR*constpcName,unsignedportSHORTusStackDepth,void*pvParameters,unsignedportBASE_TYPEuxPriority,xTaskHandle*pxCreatedTask){signedportBASE_TYPExReturn;tskTCB*pxNewTCB;#if(configUSE_TRACE_FACILITY==1)staticunsignedportBASE_TYPEuxTaskNumber=0;#endifpxNewTCB=prvAllocateTCBAndStack(usStackDepth);if(pxNewTCB!=NULL){portSTACK_TYPE*pxTopOfStack;prvInitialiseTCBVariables(pxNewTCB,pcName,uxPriority);#ifportSTACK_GROWTH0{pxTopOfStack=pxNewTCB-pxStack+(usStackDepth-1);}#else{pxTopOfStack=pxNewTCB-pxStack;}#endifpxNewTCB-pxTopOfStack=pxPortIni
本文标题:FreeRTOS任务管理分析
链接地址:https://www.777doc.com/doc-5891734 .html