2.0 任务管理数据结构

(一)

既然这的一章是讲关于任务管理,那便需要一些“ID CARD”来识别不同的任务;用术语来说,便是任务控制块,是一种struct,名为OS_TCB。

这里引用 engineer 一篇博客里的比喻:

      “ 任务控制块相当于一个任务的身份证,系统就是通过任务控制块来感知管理任务,没有任务控制块的任务不能被系统承认和管理。ucos把所有任务控制块链接为两条链表,并通过他们管理各个任务

 

(二)思维导图

 

 ps:

 1、⑥、⑦、⑧中定义类型有两种,INT8U和INT16U;

 

 2、在参考书上,任务堆栈,本是有这么一个定义:

OS_STK TaskStk[OS_MAX_TASKS][TASK_STK_SIZE]

但我的工程里找不到这样的代码,取而代之的是图中所示③、④和⑤;③负责统计,④负责空闲,至于⑤,负责定时器之类的吧。

也许是我疏忽,如果以后找到对应的代码,会有改正;

 

(三)分析

  1、任务控制块OS_TCB

   上源码

  

 1 typedef struct os_tcb {
 2     OS_STK          *OSTCBStkPtr;           /* Pointer to current top of stack                         */
 3 
 4 #if OS_TASK_CREATE_EXT_EN > 0
 5     void            *OSTCBExtPtr;           /* Pointer to user definable data for TCB extension        */
 6     OS_STK          *OSTCBStkBottom;        /* Pointer to bottom of stack                              */
 7     INT32U           OSTCBStkSize;          /* Size of task stack (in number of stack elements)        */
 8     INT16U           OSTCBOpt;              /* Task options as passed by OSTaskCreateExt()             */
 9     INT16U           OSTCBId;               /* Task ID (0..65535)                                      */
10 #endif

 留意一下这一块的line1 和line 2, 两个os_tcb的指针,会出现在接下来的分析中。

 1 struct os_tcb   *OSTCBNext;             /* Pointer to next     TCB in the TCB list                 */
 2 struct os_tcb   *OSTCBPrev;             /* Pointer to previous TCB in the TCB list                 */
 3 
 4 #if (OS_EVENT_EN) || (OS_FLAG_EN > 0)
 5     OS_EVENT        *OSTCBEventPtr;         /* Pointer to          event control block                 */
 6 #endif
 7 
 8 #if (OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0)
 9     OS_EVENT       **OSTCBEventMultiPtr;    /* Pointer to multiple event control blocks                */
10 #endif
11 
12 #if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
13     void            *OSTCBMsg;              /* Message received from OSMboxPost() or OSQPost()         */
14 #endif
15 
16 #if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
17 #if OS_TASK_DEL_EN > 0
18     OS_FLAG_NODE    *OSTCBFlagNode;         /* Pointer to event flag node                              */
19 #endif
20     OS_FLAGS         OSTCBFlagsRdy;         /* Event flags that made task ready to run                 */
21 #endif

插播冷笑话:  问:为什么笑话总以小明为主角;答:因为笑点低的看到小明就笑了:-) 来自知乎

 1     INT16U           OSTCBDly;              /* Nbr ticks to delay task or, timeout waiting for event   */
 2     INT8U            OSTCBStat;             /* Task      status                                        */
 3     INT8U            OSTCBStatPend;         /* Task PEND status                                        */
 4     INT8U            OSTCBPrio;             /* Task priority (0 == highest)                            */
 5 
 6     INT8U            OSTCBX;                /* Bit position in group  corresponding to task priority   */
 7     INT8U            OSTCBY;                /* Index into ready table corresponding to task priority   */
 8 #if OS_LOWEST_PRIO <= 63
 9     INT8U            OSTCBBitX;             /* Bit mask to access bit position in ready table          */
10     INT8U            OSTCBBitY;             /* Bit mask to access bit position in ready group          */
11 #else
12     INT16U           OSTCBBitX;             /* Bit mask to access bit position in ready table          */
13     INT16U           OSTCBBitY;             /* Bit mask to access bit position in ready group          */
14 #endif
15 
16 #if OS_TASK_DEL_EN > 0
17     INT8U            OSTCBDelReq;           /* Indicates whether a task needs to delete itself         */
18 #endif
19 
20 #if OS_TASK_PROFILE_EN > 0
21     INT32U           OSTCBCtxSwCtr;         /* Number of time the task was switched in                 */
22     INT32U           OSTCBCyclesTot;        /* Total number of clock cycles the task has been running  */
23     INT32U           OSTCBCyclesStart;      /* Snapshot of cycle counter at start of task resumption   */
24     OS_STK          *OSTCBStkBase;          /* Pointer to the beginning of the task stack              */
25     INT32U           OSTCBStkUsed;          /* Number of bytes used from the stack                     */
26 #endif
27 
28 #if OS_TASK_NAME_SIZE > 1
29     INT8U            OSTCBTaskName[OS_TASK_NAME_SIZE];
30 #endif
31 } OS_TCB;

关于这个struct里的内容,以后学到一个reference回来一个!
  

  2、空闲列表和就绪列表

    嗯,讲到空闲列表,就要提到上面的两个os_tcb指针 *OSTCBPrev *OSTCBNext,分别指向上一个节点和下一个节点。

    任务控制块相当于一个任务的身份证,系统就是通过任务控制块来感知管理任务,没有任务控制块的任务不能被系统承认和管理。ucos把所有任务控制块链接为两条链表,并通过他们管理各个任务

    众所周知,人们在管理某种证件时,总是要按照预测的数目先印制一定数量的空白证,以后当有人申请该证件时,就可以及时拿到一个空白证并填上该申请人的信息,从而快速形成一个有效证件,其目的就是提高办事效

    这就是空闲链表和就绪列表之间的关系了。

 

 

流程图看完,看点具体的表示:

(1)没有创建任何任务时的空闲链表(我们讲到系统初始化OSInit那一节中看到一个函数OS_InitTCBList(), 它便是初始化这个链表的函数 )

    这里可能出现几个变量,在三个图全部放完之后会有个表格来说明其作用

 

(2)创建一个任务后的空闲链表和就绪链表

 

3、创建两个任务后的空闲链表和就绪链表

 

这里说明一点,我所参考的教材,即卢有亮的那本《嵌入式实时操作系统中uc/os原理和实践》中关于创建了2个空闲链表和就绪链表的图,好像是错误的……

 

4、变量名

这里出现了一些变量名,说多也不多,但当初把我吓退了,遂列之。(这里表格用不惯,贴图)

 

  3、任务优先级指针表

  使用任务优先级指针表,是为了在严格的实时系统操作中,节约寻找任务控制块的时间。

  假设我们创建一个任务,这个任务的优先级为5,之后取得任务控制块(OS_TCB结构,还记得吗)的地址,简单地把地址赋值给OSTCBPrioTbl[5],这样以后就可以用过这个指针表,直接引用任务控制块了。

1   OS_TCB           *OSTCBPrioTbl[OS_LOWEST_PRIO + 1];

特意打上了红字,为了让眼睛在这上面多停留0.1s,接下来上个图,把第2小节和第3小节联系在一块儿。

看,有OS_TCB, OSTCBStkptr, OSTCBNext, OSTCBPrev, OSTCBList, 还有这一节所讲的OSTCBPrioTbl[]

接下里,我们即将接触任务堆栈,上图中的变量OSTCBStkptr, OSTCBStkBottom(抱歉,图中T打错打成R了)都与任务堆栈有关。

至于OS_TaskStat(),和OS_TaskIdle()这两个函数,分别是优先级为62的统计任务和优先级为63的空闲任务。我们会在这一章的最后分析这两个任务。其实这俩货在最开始整章的思维导图中露过脸哦。。。

 

  4、任务堆栈

  说起堆栈,我想接触到ucos的人应该都对这个名词有个概念性的理解。

  书上有一句:“这里我们定义了最多用户任务整个堆栈(OS_MAX_TASKS),而统计任务和空闲任务的堆栈是单独定义的,分别是OSTaskStatStk和OSTaskIdleStk,这里不再赘述”。

  嗯,结果我在源码中没找到正宗的stack,只找到不再赘述的OSTaskStatStk和OSTaskIdleStk。为了不缺失内容,我决定暂时把书上内容搬上去。

  我不爱写文字,如果想参考比较深入的任务堆栈分析,请参考这个帖子.

  堆栈有两种增长形式,一种是地址向下增长,PC便是采用这样的堆栈;一种是地址向上增长的。作为嵌入式操作系统应该可以移植到不同的平台,因此必须兼容两种模式。

  为了说明上面这句话,引用书上的一张图。

  

  这图的操作,是把0x0012ff78这个值压入堆栈中(这里用的是大端法还是小端法?小端!),在两种不同类型的堆栈(一为地址向上增长,一为地址向下增长)的内存模型实现。

  这里有一个亮点,我觉得是亮点,就是&TaskStk[0][TASK_STK_SIZE -1]这个。这说明ucos中的堆栈,是平面的,而非线性的。我觉得挺有意思的。

  然后,书上有一句话:"注意的是用户堆栈是可以由自己定义的,并非一定要采用二维数组的形式"。

  最后,把关于任务堆栈的几个变量给梳理一下。上表

    

  

  5、任务就绪表和就绪组

  这是这篇博文的最后一小节,主要介绍就绪表和就绪组两个数据结构,围绕他们定义了两张查找表。

  这一小节,主要描述的是如何快速进行任务调度(用就绪表和就绪组),在我看来更多的是描述算法方面,而且是很有意思的算法。

  具体的可以参考此岸幸福的这篇博文。

  在我看来算法的描述最直观的莫过于gif类的动态图了,但没那水平,便不赘述了!

 

 

 

 

 

 

posted on 2013-06-14 18:59 shivency 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/shivency/archive/2013/06/14/3127378.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值