转自:http://blog.csdn.net/wuwuhuizheyisheng/article/details/8473080?utm_source=tuicool
操作系统的调度都围绕这一个数据结构体OS_TCB,我们叫它任务控制块。
任务控制块贯穿了整个uCOS2操作系统,如果不了解这个结构体在操作系统当中的用法,那就不可能对uCOS2深入的理解。
在Ucos_ii.h当中有一个
OS_EXT OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS]; /* Table of TCBs */
它是定义一个或者外部声明一个OSTCBTbl的数组。这两个作用需要靠OS_GLOBALS是否宏定义来选择。当然在整个程序代码当中可能只有一个C文件中定义了OSTCBTbl变量,其他的C文件中只是对它进行外部变量声明。
在Linux操作系统编写增加链表和删除链表程序时,都会伴随着内存空间的申请和释放。但是在uCOS2操作系统当中没有这么强悍的内存管理。一个任务控制块OS_TCB管理者一个任务,所以OSTCBTbl的元素个数必须大于在应用程序当中建立的任务数。从定义中可以看出元素个数由两个宏定义决定,第一OS_MAX_TASKS:就是在应用程序当中可能建立的最大任务数,第二OS_N_SYS_TASKS:是调用系统函数后有系统建立的任务数。这两个数值是可以改变的,因为在程序当中必须要有一个空闲任务,而计算CPU效率的统计任务是由用户选择的,所以OS_N_SYS_TASKS的值受到OS_TASK_STAT_EN的控制。宏定义OS_TASK_STAT_EN的值决定了,是否使能统计任务。
#if OS_TASK_STAT_EN > 0
#define OS_N_SYS_TASKS 2u /* Number of system tasks */
#else
#define OS_N_SYS_TASKS 1u
#endif
任务控制块主要由两个链表来控制,一个是正在使用的任务控制块链表OSTCBList和空闲任务控制块链表OSTCBFreeList。OSTCBList是一个双向链表,只要知道了链表当中的一个元素就能够找到该链表中所有的元素,即能访问每一个任务。OSTCBFreeList是一个单向链表,存储着还没有使用的任务控制块。需要建立一个任务时,就会从空闲任务控制块OSTCBFreeList中取出一个任务控制块,并将空闲任务控制块指针OSTCBFreeList指向下一个空闲任务控制块。从空闲任务控制链表中取出的任务控制块(暂且把该任务控制块叫做OSTCB1)后,需要将人任务控制块加入到任务控制块双向链表OSTCBList中,该任务控制块指针指向了最后一个加入到任务控制块链表的任务控制块。将OSTCB1当中的任务控制块指针OSTCBNext指向OSTCBList指向的任务控制块,OSTCBList指向的任务控制块当中也有指向任务控制块的变量OSTCBPrev,将OSTCBPrev指向OSTCB1任务控制块。然后再将OSTCBList指向OSTCB1任务控制块,这样就将新的任务控制块加入到了任务控制块链表当中。
系统初始化后,两链表OSTCBList,OSTCBFreeList的形式。查看源码文件Os_core.c,在文件中有一个函数OSInit()。这个函数必须被应用程序调用,并且只能调用一次。该函数中调用了OS_InitTCBList。在OS_InitTCBList函数中对与任务控制块相关联的代码进行初始化。源码如下:
static void OS_InitTCBList (void)
{
INT8U i;
OS_TCB *ptcb1;
OS_TCB *ptcb2;
OS_MemClr((INT8U *)&OSTCBTbl[0], sizeof(OSTCBTbl)); /* Clear all the TCBs */
OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl)); /* Clear the priority table */
ptcb1 = &OSTCBTbl[0];
ptcb2 = &OSTCBTbl[1];
for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) { /* Init. list of free TCBs */
ptcb1->OSTCBNext = ptcb2;
#if OS_TASK_NAME_SIZE > 1
ptcb1->OSTCBTaskName[0] = '?'; /* Unknown name */
ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
ptcb1++;
ptcb2++;
}
ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */
#if OS_TASK_NAME_SIZE > 1
ptcb1->OSTCBTaskName[0] = '?'; /* Unknown name */
ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
OSTCBList = (OS_TCB *)0; /* TCB lists initializations */
OSTCBFreeList = &OSTCBTbl[0];
}
函数OS_MemClr可以对参数中所指示的空间进行清零。第一个参数是空间对象的首地址,第二个参数是需要清零的空间大小(以字节为单位)。对于具体的源码可以自行分析,在此不再叙述。
在程序当中蓝色的代码将OSTCBTbl中的所有的元素组成一个单向的链表,最有一个元素中的任务控制块指针OSTCBNext 指向空。
初始化的时候并没有任何的任务被创建,所以在程序当中 OSTCBList 指向了空。