上面讲解了空闲任务的建立过程,空闲任务是系统自动建立的,无论你是否需要它都必然会被建立。
其实用户任务的建立过程和空闲任务完全一样,同样也是栈空间初始化,变量初始化,把任务信息与那几个链表关联起来。
现在举一个例子,我要新建一个优先级为10的启动任务。
1 int main(void) 2 { 5 OSInit(); 6 OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],10); 7 OSStart(); 8 }
但我们需要建立用户任务的时候,调用的也是OSTaskCreate函数,这样又回到了空闲任务的那个过程。
过程暂且不表,我们直接看结果。
启动任务建立之前,那几个数组和链表的状态如下:
数组OSTCBTbl的第0个位置和第1个位置都有任务(栈空间指向不为空),第2个位置就没有任务了(栈空间指向为空),这个状态表明现在我们有两个任务(空闲任务&统计任务)。
同样在优先级数组:OSTCBPrioTbl中我们也可以看到这个情况,这个数组是按照任务的优先级排序的,现在只有最后两个位置非空,也就是说只有这两个任务存在(仔细看数据的内容,可以看到是和上面的任务数组完全一样的)
当我们新建了那个优先级为10的任务以后,这两个数组的状态变化如下:
任务数组的第2个位置刚才还是空的,现在已经有数据了(这个数组里面的的任务信息是按照建立顺序来排序的)。
优先级数组的第10个位置刚才还是空的,现在也有数据了(这个数组里面的的任务信息是按照优先级来排序的)。
这就说明,优先级为10的任务已经被建立。
※题外话:大家有没有觉得这个任务优先级管理数组长得有点像哈希表的链路法?只不过人家是横着哈,这个表是竖着哈!哈哈哈!
任务建立以后,系统就要启动,这是调用函数:
1 void OSStart (void) 2 { 3 if (OSRunning == OS_FALSE) { 4 OS_SchedNew(); /* Find highest priority's task priority number */ 5 OSPrioCur = OSPrioHighRdy; 6 OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */ 7 OSTCBCur = OSTCBHighRdy; 8 OSStartHighRdy(); /* Execute target specific code to start task */ 9 } 10 }
其中OS_SchedNew的作用请参考(http://www.cnblogs.com/han-bing/p/8882375.html),它的作用就是找到当前系统中优先级最高的那个任务,除了优先级为10的任务之外,当前我们只建立了空闲任务和统计任务,这两个任务的优先级是最低的,因此经过了这个函数的处理后,系统找出来的肯定是优先级为10的任务。
然后把这个任务的信息,装载到相应的链表和变量中,最后调用OSStartHighRdy函数使PC指针跳进任务10中去执行。
这样,UCOSII操作系统就开始启动,接下来便是任务调度。
至于任务的删除,挂起,变更优先级等等处理,各位可以自行调试,原理都一样,对任务数组和任务状态的操作罢了!
完结!