μC/OS-II的任务管理
OSTaskStkChk()函数的代码如程序清单L4.10所示。0S_STK_DATA(参看μCOS_Ⅱ.H)数据结构用来保存有关任务堆栈的信息。笔者打算用一个数据结构来达到两个目的。第一,把OSTaskStkChk()当作是查询类型的函数,并且使所有的查询函数用同样的方法返回,即返回查询数据到某个数据结构中。第二,在数据结构中传递数据使得笔者可以在不改变OSTaskStkChk()的API(应用程序编程接口)的条件下为该数据结构增加其它域,从而扩展OSTaskStkChk()的功能。现在,0S_STK_DATA只包含两个域:OSFree和OSUsed。从代码中用户可看到,通过指定执行堆栈检验的任务的优先级可以调用OSTaskStkChk()。如果用户指定0S_PRIO_SELF[L4.10(1)],那么就表明用户想知道当前任务的堆栈信息。当然,前提是任务已经存在[L4.10(2)]。要执行堆栈检验,用户必须已用OSTaskCreateExt()建立了任务并且已经传递了选项OS_TASK_OPT_CHK[L4.10(3)]。如果所有的条件都满足了,OSTaskStkChk()就会象前面描述的那样从堆栈栈底开始统计堆栈的空闲空间[L4.10(4)]。 最后,储存在0S_STK_DATA中的信息就被确定下来了[L4.10(5)]。注意函数所确定的是堆栈的实际空闲字节数和已被占用的字节数,而不是堆栈的总字节数。当然,堆栈的实际大小(用 字节表示)就是该两项之和。 程序清单 L4.10 堆栈检验函数 INT8UOSTaskStkChk(INT8Uprio,OS_STK_DATA*pdata) { OS_TCB*ptcb; OS_STK*pchk; INT32Ufree; INT32Usize; pdata->OSFree=0; pdata->OSUsed=0; if(prio>OS_LOWEST_PRIOprio!=OS_PRIO_SELF){ return(OS_PRIO_INVALID); } OS_ENTER_CRITICAL(); if(prio==OS_PRIO_SELF){(1) prio=OSTCBCur->OSTCBPrio; } ptcb=OSTCBPrioTbl[prio]; if(ptcb==(OS_TCB*)0){(2) OS_EXIT_CRITICAL(); return(OS_TASK_NOT_EXIST); } if((ptcb->OSTCBOptOS_TASK_OPT_STK_CHK)==0){(3) OS_EXIT_CRITICAL(); return(OS_TASK_OPT_ERR); } free=0; (4) size=ptcb->OSTCBStkSize; pchk=ptcb->OSTCBStkBottom; OS_EXIT_CRITICAL(); #ifOS_STK_GROWTH==1 while(*pchk++==0){ free++; } #else while(*pchk--==0){ free++; } #endif pdata->OSFree=free*sizeof(OS_STK);(5) pdata->OSUsed=(size-free)*sizeof(OS_STK); return(OS_NO_ERR); } 4.4删除任务,OSTaskDel() 有时候删除任务是很有必要的。删除任务,是说任务将返回并处于休眠状态(参看3.02,任务状态),并不是说任务的代码被删除了,只是任务的代码不再被μC/OS-Ⅱ调用。通过调用OSTaskDel()就可以完成删除任务的功能(如程序清单L4.11所示)。OSTaskDel()一开始应确保用户所要删除的任务并非是空闲任务,因为删除空闲任务是不允许的[L4.11(1)]。不过,用户可以删除statistic任务[L4.11(2)]。接着,OSTaskDel()还应确保用户不是在ISR例程中去试图删除一个任务,因为这也是不被允许的[L4.11(3)]。调用此函数的任务可以通过指定OS_PRIO_SELF参数来删除自己[L4.11(4)]。接下来OSTaskDel()会保证被删除的任务是确实存在的[L4.11(3)]。如果指定的参数是OS_PRIO_SELF的话,这一判断过程(任务是否存在)自然是可以通过的,但笔者不准备为这种情况单独写一段代码,因为这样只会增加代码并延长程序的执行时间。 程序清单 L4.11 删除任务 INT8UOSTaskDel(INT8Uprio) { OS_TCB*ptcb; OS_EVENT*pevent; if(prio==OS_IDLE_PRIO){(1) return(OS_TASK_DEL_IDLE); } if(prio>=OS_LOWEST_PRIOprio!=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->
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
