新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > μC/OS-II的任务管理

μC/OS-II的任务管理

作者: 时间:2016-10-08 来源:网络 收藏

这样,OSTaskDel()就能处理中断服务了,但由于它增加了 OSLockNesting,ISR执行完后会返回到被中断任务,从而继续任务的删除工作。注意OSTaskDel()此时还没有完全完成删除任务的工作,因为它还需要从TCB链中解开OS_TCB,并将OS_TCB返回到空闲OS_TCB表中。

另外需要注意的是,笔者在调用OS_EXIT_CRITICAL()函数后,马上调用了OSDummy()[L4.11(12)],该函数并不会进行任何实质性的工作。这样做只是因为想确保处理器在中断允许的情况下至少执行一个指令。对于许多处理器来说,执行中断允许指令会强制CPU禁止中断直到下个指令结束!Intel80x86和ZilogZ-80处理器就是如此工作的。开中断后马上关中断就等于从来没开过中断,当然这会增加中断的响应时间。因此调用OSDummy()确保在再次禁止中断之前至少执行了一个调用指令和一个返回指令。当然,用户可以用宏定义将OSDummy()定义为一个空操作指令(译者注:例如MC68HC08指令中的NOP指令) ,这样调用OSDummy()就等于执行了一个空操作指令,会使OSTaskDel()的执行时间稍微缩短一点。但笔者认为这种宏定义是没价值的,因为它会增加移植μCOS-Ⅱ的工作量。

现在,OSTaskDel()可以继续执行删除任务的操作了。在OSTaskDel()重新关中断后,它通过锁定嵌套计数器(OSLockNesting)减一以重新允许任务调度[L4.11(13)]。接着,OSTaskDel()调用用户自定义的OSTaskDelHook()函数[L4.11(14)],用户可以在这里删除或

释放自定义的TCB附加数据域。 然后, OSTaskDel()减少μCOS-Ⅱ的任务计数器。 OSTaskDel()

简单地将指向被删除的任务的OS_TCB的指针指向NULL[L4.11(15)],从而达到将OS_TCB从优先级表中移除的目的。再接着,OSTaskDel()将被删除的任务的OS_TCB从OS_TCB双向链表中移除[L4.11(16)]。 注意,没有必要检验ptcb->OSTCBNext==0的情况, 因为OSTaskDel()不能删除空闲任务,而空闲任务就处于链表的末端(ptcb->OSTCBNext==0)。接下来,OS_TCB返回到空闲OS_TCB表中,并允许其它任务的建立[L4.11(17)]。最后,调用任务调度程序来查看在OSTaskDel()重新允许中断的时候[L4.11(11)],中断服务子程序是否曾使更高优先级的任务处于就绪状态[L4.11(18)]。

4.5请求删除任务,OSTaskDelReq()

有时候,如果任务A拥有内存缓冲区或信号量之类的资源,而任务B想删除该任务,这些资源就可能由于没被释放而丢失。在这种情况下,用户可以想法子让拥有这些资源的任务在使用完资源后,先释放资源,再删除自己。用户可以通过OSTaskDelReq()函数来完成该功能。

发出删除任务请求的任务(任务B)和要删除的任务(任务A)都需要调用OSTaskDelReq()函数。任务B的代码如程序清单L4.12所示。任务B需要决定在怎样的情况下请求删除任务[L4.12(1)]。换句话说,用户的应用程序需要决定在什么样的情况下删除任务。如果任务需要被删除,可以通过传递被删除任务的优先级来调用OSTaskDelReq()[L4.12(2)]。如果要被删除的任务不存在(即任务已被删除或是还没被建立),OSTaskDelReq()返回OS_TASK_NOT_EXIST。如果OSTaskDelReq()的返回值为OS_NO_ERR,则表明请求已被接受但任务还没被删除。用户可能希望任务B等到任务A删除了自己以后才继续进行下面的工作,这时用户可以象笔者一样,通过让任务B延时一定时间来达到这个目的[L4.12(3)]。笔者延时了一个时钟节拍。如果需要,用户可以延时得更长一些。当任务A完全删除自己后,[L4.12(2)]中的返回值成为0S_TASK_NOT_EXIST,此时循环结束[L4.12(4)]。

程序清单 L4.12 请求删除其它任务的任务(任务B)

voidRequestorTask(void*pdata)

{

INT8Uerr;

pdata=pdata;

for(;;){

/* 应用程序代码 */

if('TaskToBeDeleted()' 需要被删除){(1)

while(OSTaskDelReq(TASK_TO_DEL_PRIO)!=OS_TASK_NOT_EXIST){(2)

OSTimeDly(1);(3)

}

}

/*应用程序代码*/(4)

}

}

程序清单 L4.13 需要删除自己的任务(任务A)

voIDTaskToBeDeleted(void*pdata)

{

INT8Uerr;

pdata=pdata;

for(;;){

/*应用程序代码*/

If(OSTaskDelReq(OS_PRIO_SELF)==OS_TASK_DEL_REQ){(1)

释放所有占用的资源;(2)

释放所有动态内存;

OSTaskDel(OS_PRIO_SELF);(3)

}else{

/*应用程序代码*/

}

}

}

需要删除自己的任务(任务A)的代码如程序清单L4.13所示。在OS_TAB中存有一个标志,任务通过查询这个标志的值来确认自己是否需要被删除。这个标志的值是通过调用OSTaskDelReq(OS_PRIO_SELF)而得到的。当OSTaskDelReq()返回给调用者OS_TASK_DEL_REQ[L4.13(1)]时,则表明已经有另外的任务请求该任务被删除了。在这种情况下,被删除的任务会释放它所拥有的所用资源[L4.13(2)],并且调用OSTaskDel(OS_PRIO_SELF)来删除自己[L4.13(3)]。前面曾提到过,任务的代码没有被真正的删除,而只是μC/OS-Ⅱ不再理会该任务代码,换句话说,就是任务的代码不会再运行了。

但是,用户可以通过调用OSTaskCreate()或OSTaskCreateExt()函数重新建立该任务。OSTaskDelReq()的代码如程序清单L4.14所示。通常OSTaskDelReq()需要检查临界条件。首先,如果正在删除的任务是空闲任务,OSTaskDelReq()会报错并返回[L4.14(1)]。接着,它要保证调用者请求删除的任务的优先级是有效的[L4.14(2)]。如果调用者就是被删除任务本身,存储在OS_TCB中的标志将会作为返回值[L4.14(3)]。如果用户用优先级而不是OS_PRIO_SELF指定任务,并且任务是存在的[L4.14(4)],OSTaskDelReq()就会设置任务的内部标志[L4.14(5)]。如果任务不存在,OSTaskDelReq()则会返回OS_TASK_NOT_EXIST,表明任务可能已经删除自己了[L4.14(6)]。

程序清单 L4.14 OSTaskDelReq().

INT8UOSTaskDelReq(INT8Uprio)

{

BOOLEANstat;

INT8Uerr;

OS_TCB*ptcb;

if(prio==OS_IDLE_PRIO){(1)

return(OS_TASK_DEL_IDLE);

}

if(prio>=OS_LOWEST_PRIOprio!=OS_PRIO_SELF){



关键词:

评论


相关推荐

技术专区

关闭