自己仿写一个ucosii(二) 任务控制块的简析

任务控制块是任务管理的核心数据结构,任务控制块的数量就是操作系统最多可处理任务的数量。ucosii目测一般都是10个以下的任务。


空闲任务链表和就绪任务链表。在初始化ucos时,我们会创建一个空闲任务链表,里面包含最大任务数量。而创建一个任务时,我们会
摘下一个任务块(链表的节点),然后通过 任务创建函数将相关的参数赋值给任务块,再把任务块放进就绪链表中。


下面具体看看任务控制块中需要些什么东西:


1.堆栈指针及一段内存空间:  由于我们要保存任务的信息,才能使任务间相互切换,所以要使用堆栈。堆栈存储相关的局部
变量和子函数函数调用,这些空间的大小是我们手动分配的(指定好大小的全局数组)。在堆栈初始化中,将程序入口指针(任务函数地址)
也放进堆栈。
    
注意啦,堆栈必须放在任务块的最前面(控制块的堆栈指针必须定义在第一个变量处),因为任务调度时,调度器给出的是任务控制块
的首地址,程序指针指向当前任务块,执行下面的代码,这里要说的是,任务块本身并不直接包含任务代码,而是让程序指针间接地指
向一段while(1)循环。 当我们进行任务切换时,找到当前就绪最高优先级的控制块,触发PendSV,相关参数入栈, 进入中断服务程序。
中断服务程序将 当前任务指针指向当前最高优先级任务控制块。中断服务程序结束,程序指针指向 当前任务控制块,直接进入任务堆栈,
读出当前任务堆栈信息。这个过程与中断返回的过程是相似的,只是中断返回是cpu自动保存当前环境,中断服务程序结束后自动将中断前
环境恢复,而任务切换则是在中断服务程序中改变程序指针,在中断返回时 弹出另外一个堆栈的内容。 


2.任务块加入就绪链表


3.任务自身的属性,比如优先级,任务ID等    另外任务延时也在这里


4.事件管理,用于记录任务相关的信号量、消息和队列等信息


5.任务优先级记录的相关条目,用于快速查找新就绪的任务,置位和取消这些任务就靠这几位


6.任务链表指针

以下是我理解的一个最简单的任务控制块,不包含事件管理的功能


typedef struct tcb
{

DCOS_STK *DCOS_StkPtr; //任务堆栈地址
INT16U    DCOS_StkSize;

int init_flag;     //任务控制块初始化标志位
char *code_name;     //任务控制块字符串参数

int run_state;       //任务控制块任务当前状态             
int prio;            //任务优先级

long int tick;   //任务延时定时器

void (* fun)(); //任务函数指针
void *p_arg; //任务参数

unsigned char DCOS_BX;
unsigned char DCOS_BY;
unsigned char DCOS_BBitX;
unsigned char DCOS_BBitY;

struct tcb *next;  //指向链表的下一个任务控制块
struct tcb *prior;  //指向链表的上一个任务控制块
}DCOS_TCB;

你可能感兴趣的:(自己仿写一个ucosii(二) 任务控制块的简析)