ucos-ii的任务控制块 .

在操作系统初始化函数OSInit执行之后,用户可以调用OSTaskCreate或者OSTaskCreateExt函数来创建用户任务,因为这两个函数是内核用来创建任务的,不允许用户进行修改,因此被称为系统服务。用户任务的程序是以函数的形式游用户编写,称为用户函数,和操作系统提供的服务划分了界限,很明显,必须将用户函数的地址传递给创建任务的系统服务。在用户任务中,同样可以调用OSTaskCreate或者OSTaskCreateExt函数来创建其他的任务,也可以调用OSTaskDel来删除其他任务或调用请求删除任务的函数提交删除任务的请求,还可以调用OSTaskSuspend来暂时取消任务或者其他任务的执行。
      因为ucos-ii采用的是抢占式多任务调度算法,因此任务的优先级是至关重要的,是任务唯一的标志,因此各个任务的优先级必须不同。任务的优先级和任务的其他信息,如任务的堆栈地址、任务的状态、任务的等待时间指针、任务的延时时间等信息都保存在一个名为任务控制块的数据结构中,不掌握任务控制块(TCB)就无法研究和掌握任务管理。
      除了任务控制块外,ucos-ii中还设计了就绪组和就绪表来标志就绪的任务。就绪的任务可能不止一个,但有一个上限----不能超过63个!。任务调度程序(时钟中断服务子程序)每隔一段时间会执行一次,具体的时间取决用户对时钟中断的设置。如果设置为20ms,则每隔20ms就要进行一次任务调度。这就要从就绪组和就绪表中超找到优先级最高的就绪任务了。因为是实时性很高的操作系统,不允许查找最高优先级的任务的时间太长,不能因为任务多了查找起来就慢,任务少了查找起来就快。实际上ucos-ii的任务调度的时间在一个指定的嵌入式环境中是确定的。为了达到这一点,我们设计了巧妙的数据结构和算法来实现这一过程。
      为了根据优先级这一任务的唯一标识来找到任务的各种属性,从而执行不同的处理,设计了任务优先级指针表OSTCBPrioTbl来快速找到任务的控制块。为了迅速的得到当前任务的控制块,有定义了任务快指针OSTCBCur来指示当前的任务。
    任务管理的数据结构包括了任务控制块、任务空闲链表和任务就绪链表、任务优先级指针表、任务堆栈等,是ucos内核的核心内容之一,离开这些数据结构,内核什么功能也完成不了。
    1任务控制块的定义
任务控制块是任务管理的核心数据结构,操作系统在启动的时候,首先在内存中创建一定数量的任务控制块。任务控制块的数量等于操作系统能同时管理的最多的任务数。
     ucos-ii将任务控制块划分为两个链表:就绪链表和空闲链表。创建一个任务,就是从空闲链表中取出一个空闲的任务控制块,将任务的各种属性添加到控制块中,并将该任务控制块移到就绪表中,更改就绪表和据需组,任务就从睡眠态转换到就绪态,当没有更高优先级的任务在运行时,任务就可以得到运行。相反,要结束一个任务的运行,就要将该任务的任务控制块从就绪链表移到空闲链表,然后修改就绪组和就绪表,取消任务的就绪标志,任务就从就绪态转换到其他态,而只有再回到就绪态才有可能得到运行。
     在给出就绪链表和空闲链表之前,首先需要掌握任务控制块的基本结构,该结构体在ucos_ii.h文件中。
     如下代码给出了任务控制块结构体的定义:
 
     

typedef struct os_tcb {
    OS_STK          *OSTCBStkPtr; /* 当前任务堆栈栈顶的指针 */

#if OS_TASK_CREATE_EXT_EN > 0
    void            *OSTCBExtPtr;      /*扩展块的指针*/
    OS_STK          *OSTCBStkBottom;   /*任务堆栈栈底的指针*/
    INT32U           OSTCBStkSize;     /* 任务堆栈的大小*/
    INT16U           OSTCBOpt;         /* 扩展的选项*/
    INT16U           OSTCBId;          /* 任务ID,因为当前以任务的优先级为任务的唯一标识,所以实际使用时常使该项的值等于任务优先级*/
#endif

    struct os_tcb   *OSTCBNext;        /*指向下一个任务控制块的指针*/
    struct os_tcb   *OSTCBPrev;        /* 指向前一个任务控制块的指针*/

#if OS_EVENT_EN || (OS_FLAG_EN > 0)
    OS_EVENT        *OSTCBEventPtr;    /* 指向事件控制块的指针*/
#endif

#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
    void            *OSTCBMsg;         /* 来自于OSMboxPost()orOSQPost()的消息指针*/
#endif

#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
#if OS_TASK_DEL_EN > 0
    OS_FLAG_NODE    *OSTCBFlagNode;    /* 事件标志节点指针*/
#endif
    OS_FLAGS         OSTCBFlagsRdy;    /* 使任务就绪并运行的事件标志*/
#endif

    INT16U           OSTCBDly;         /* 任务延迟的时钟节拍数或者是等待事件的超时时间*/
    INT8U            OSTCBStat;        /* 任务状态:睡眠、就绪、运行、等待、被中断等*/
    INT8U            OSTCBStatPend;    /* 事件等待标志*/
    INT8U            OSTCBPrio;        /* 任务优先级,0为最高*/

    INT8U            OSTCBX;           /* Bit position in group  corresponding to task priority        */
    INT8U            OSTCBY;           /* Index into ready table corresponding to task priority  */
#if OS_LOWEST_PRIO <= 63
    INT8U            OSTCBBitX;        /* Bit mask to access bit position in ready table               */
    INT8U            OSTCBBitY;        /* Bit mask to access bit position in ready group */
#else
    INT16U           OSTCBBitX;        /* Bit mask to access bit position in ready table */
    INT16U           OSTCBBitY;        /* Bit mask to access bit position in ready group               */
#endif

#if OS_TASK_DEL_EN > 0
    INT8U            OSTCBDelReq;/* 任务删除请求标志 */
#endif

#if OS_TASK_PROFILE_EN > 0
    INT32U           OSTCBCtxSwCtr;    /* 切换到该任务的次数*/
    INT32U           OSTCBCyclesTot;   /* 任务已经运行的总的时钟周期数*/
    INT32U           OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption*/
    OS_STK          *OSTCBStkBase;     /* 任务堆栈的起始地址 */
    INT32U           OSTCBStkUsed;     /* 任务堆栈中已经使用的空间*/
#endif

#if OS_TASK_NAME_SIZE > 1
    INT8U            OSTCBTaskName[OS_TASK_NAME_SIZE];//任务名称
#endif
} OS_TCB;

对程序中的任务控制块的说明如下:
(1)*OSTCBStkPtr是指向OS_STK类型的指针,OS_STK在OS_CPU.H文件中定义
  typedef unsigned int OS_STK;
因此,OS_STK就是无符号整数,OS_STK 是任务堆栈的每个数据项的类型,对于不同的硬件系统是不同的,在做移植的时候就需要进行修改。OS_CPU.H定义了和CPU相关的数据结构和全局变量
   任务堆栈的操作是最底层的,要用汇编语言来写,因此该指针在整个结构体的第一句开始定义,那么在定义结构体的实体后,控制块的0地址就存储了任务堆栈的栈顶地址,方便了汇编语言的操作。换句话说,OSTCBStkPtr是指向任务堆栈栈顶的指针,每个任务都有自己的任务堆栈,任务堆栈是进行任务切换的关键数据结构,任务运行的CPU环境,包括任务的代码的地址都保存在了任务堆栈中。
 
(2)任务状态OSTCBStat。任务状态的取值范围和对应的宏如下表所示,当任务的状态取值为OS_STAT_RDY,即0x00时,处于就绪态,可以被调度运行。
       宏                      取值               含义
   OS_STAT_RDY                 0x00               任务未等待事件且任务未挂起
   OS_STAT_SEM                 0x01               任务等待信号量
   OS_STAT_MBOX                0x02               任务等待消息邮箱
   OS_STAT_Q                   0x04               任务等待消息队列
   OS_STAT_SUSPEND             0x08               任务挂起
   OS_STAT_MUTEX               0x10               任务等待互斥信号量
   OS_STAT_FALG                0x20               任务等待事件标志
 
(3)任务优先级OSTCBPrio。每个任务都有唯一的优先级,因此在ucos-ii以优先级作为事件的标志,作为任务管理的主键,任务的优先级可以是0~63,但是优先级62和63被统计任务和空闲任务占用,用户可用的优先级可以使0~61,数字越低,优先级越高。

你可能感兴趣的:(ucosii)