ucos II任务管理之三:删除任务
有了前面的经历之后,mcu21决定全面地学习了任务的管理。这样在项目编程中才能做到“信手拈来”。
在ucos II 里,创建一个任务之后,可以对任务执行以下几种操作
1. 删除任务 OSTaskDel()
2. 挂起任务 OSTaskSuspend()
3. 恢复任务 OSTaskResume()
4. 改变任务的优先级 OSTaskChangePrio()
5. 提取任务信息 OSTaskQuery()
今天来学习下删除任务。
删除任务,是说任务将返回并处于休眠状态,任务的代码不再被μC/OS-Ⅱ调用。
删除任务不是删除任务的代码。
乍看起来,删除任务和挂起任务是有些相似的。其实有着本质的区别,根本来说,我觉得最大的不同就是删除任务有对任务控制块的操作。我们知道在任务创建的时候,需要给每一个任务分配一个任务控制块,这个任务控制块存储着关于这个任务重要的信息。对任务间切换起着至关重要的作用。
挂起任务根本来说不会动任务控制块,但删除任务就会把任务控制块从OSTCBList链表中移到OSTCBFreeList。
下面详细理解下任务删除的实现过程。
INT8U OSTaskDel (INT8U prio) |
{ |
OS_TCB *ptcb; |
OS_EVENT *pevent; |
|
if (prio == OS_IDLE_PRIO) { (1) |
return (OS_TASK_DEL_IDLE); |
} |
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { (2) |
return (OS_PRIO_INVALID); |
} |
OS_ENTER_CRITICAL(); |
if (OSIntNesting > 0) { (3) |
OS_EXIT_CRITICAL(); |
return (OS_TASK_DEL_ISR); |
} |
if (prio == OS_PRIO_SELF) { (4) |
Prio = OSTCBCur->OSTCBPrio; |
} |
if ((ptcb = OSTCBPrioTbl[prio]) != (OS_TCB *)0) { (5) |
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) { (6) |
OSRdyGrp &= ~ptcb->OSTCBBitY; |
} |
if ((pevent = ptcb->OSTCBEventPtr) != (OS_EVENT *)0) { (7) |
if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) { |
pevent->OSEventGrp &= ~ptcb->OSTCBBitY; |
} |
} |
Ptcb->OSTCBDly = 0; (8) |
Ptcb->OSTCBStat = OS_STAT_RDY; (9) |
OSLockNesting++; (10) |
OS_EXIT_CRITICAL(); (11) |
OSDummy(); (12) |
OS_ENTER_CRITICAL(); |
OSLockNesting--; (13) |
OSTaskDelHook(ptcb); (14) |
OSTaskCtr--; |
OSTCBPrioTbl[prio] = (OS_TCB *)0; (15) |
if (ptcb->OSTCBPrev == (OS_TCB *)0) { (16) |
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0; |
OSTCBList = ptcb->OSTCBNext; |
} else { |
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext; |
ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev; |
} |
ptcb->OSTCBNext = OSTCBFreeList; (17) |
OSTCBFreeList = ptcb; |
OS_EXIT_CRITICAL(); |
OSSched(); (18) |
return (OS_NO_ERR); |
} else { |
OS_EXIT_CRITICAL(); |
return (OS_TASK_DEL_ERR); |
} |
} |
仔细阅读上面程序,可以看出(1)(2)(3)(4)(5)(6)(7)和挂起任务函数,恢复任务函数基本是一样。体现了ucos II 代码的完整性。
整个过程大致如下:
1. 把要删除的任务移除就绪表
2. 把要删除的任务移除等待表
3. 避免其它任务或ISR调用OSTaskResume()
4. 阻止任务调度,以防止任务删除过程中切换到其它的任务
以上都是前戏,接下来才是高潮了,你懂的。
5. 减少μCOS-Ⅱ的任务计数器。简单地将指向被删除的任务的OS_TCB的指针指向NULL,从而达到将OS_TCB从优先级表中移除的目的。
6. 将被删除的任务的OS_TCB从OS_TCB双向链表中移除
|
|
经过以上几大步骤,一个任务删除就基本完成。