新闻中心

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

μC/OS-II的任务管理

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

INT16Ui;

OS_STK*pfill;

if(prio>OS_LOWEST_PRIO){(1)

return(OS_PRIO_INVALID);

}

OS_ENTER_CRITICAL();

if(OSTCBPrioTbl[prio]==(OS_TCB*)0){(2)

OSTCBPrioTbl[prio]=(OS_TCB*)1;(3)

OS_EXIT_CRITICAL();(4)

if(optOS_TASK_OPT_STK_CHK){(5)

if(optOS_TASK_OPT_STK_CLR){

Pfill=pbos;

for(i=0;i

#ifOS_STK_GROWTH==1

*pfill++=(OS_STK)0;

#else

*pfill--=(OS_STK)0;

#endif

}

}

}

psp=(void*)OSTaskStkInit(task,pdata,ptos,opt);(6)

err=OSTCBInit(prio,psp,pbos,id,stk_size,pext,opt);(7)

if(err==OS_NO_ERR){(8)

OS_ENTER_CRITICAL;

OSTaskCtr++;(9)

OSTaskCreateHook(OSTCBPrioTbl[prio]);(10)

OS_EXIT_CRITICAL();

if(OSRunning){(11)

OSSched();(12)

}

}else{

OS_ENTER_CRITICAL();

OSTCBPrioTbl[prio]=(OS_TCB*)0;(13)

OS_EXIT_CRITICAL();

}

return(err);

}else{

OS_EXIT_CRITICAL();

return(OS_PRIO_EXIST);

}

}

OSTaskCreateExt()一开始先检测分配给任务的优先级是否有效[L4.3(1)]。 任务的优先级必须在0到OS_LOWEST_PRIO之间。接着,OSTaskCreateExt()要确保在规定的优先级上还没有建立任务[L4.3(2)]。在使用μC/OS-Ⅱ时,每个任务都有特定的优先级。如果某个优先级是空闲的,μC/OS-Ⅱ通过放置一个非空指针在OSTCBPrioTbl[]中来保留该优先级[L4.3(3)]。这就使得OSTaskCreateExt()在设置任务数据结构的其他部分时能重新允许中断[L4.3(4)]。

为了对任务的堆栈进行检验[参看4.03,堆栈检验,OSTaskStkChk()],用户必须在opt参数中设置OS_TASK_OPT_STK_CHK标志。 堆栈检验还要求在任务建立时堆栈的存储内容都是0(即堆栈已被清零)。为了在任务建立的时候将堆栈清零,需要在opt参数中设置OS_TASK_OPT_STK_CLR。当以上两个标志都被设置好后,OSTaskCreateExt()才能将堆栈清零[L4.3(5)]。

接着,OSTaskCreateExt()调用OSTaskStkInit()[L4.3(6)],它负责建立任务的堆栈。该函数是与处理器的硬件体系相关的函数,可以在OS_CPU_C.C文件中找到。有关实现OSTaskStkInit()的细节可参看第八章——移植μC/OS-Ⅱ。如果已经有人在你用的处理器上成功地移植了μC/OS-Ⅱ,而你又得到了他的代码,就不必考虑该函数的实现细节了。

OSTaskStkInit()函数返回新的堆栈栈顶(psp),并被保存在任务的0S_TCB中。

μC/OS-Ⅱ支持的处理器的堆栈既可以从上(高地址)往下(低地址)递减也可以从下往上递增(参看4.02,任务堆栈)。用户在调用OSTaskCreateExt()的时候必须知道堆栈是递增的还是递减的(参看用户所用处理器的OS_CPU.H中的OS_STACK_GROWTH),因为用户必须得把堆栈的栈顶传递给OSTaskCreateExt(),而栈顶可能是堆栈的最低地址(当OS_STK_GROWTH

为0时),也可能是最高地址(当OS_STK_GROWTH为1时)。

一旦OSTaskStkInit()函数完成了建立堆栈的任务,OSTaskCreateExt()就调用

OSTCBInit()[L4.3(7)], 从空闲的OS_TCB缓冲池中获得并初始化一个OS_TCB。 OSTCBInit()

的代码在OSTaskCreate()中曾描述过(参看4.00节),从OSTCBInit()返回后,

OSTaskCreateExt()要检验返回代码[L4.3(8)],如果成功,就增加OSTaskCtr[L4.3(9)],

OSTaskCtr用于保存产生的任务数目。 如果OSTCBInit()返回失败, 就置OSTCBPrioTbl[prio]

的入口为0[L4.3(13)]以放弃对该任务优先级的占用。然后,OSTaskCreateExt()调用

OSTaskCreateHook()[L4.3(10)],OSTaskCreateHook()是用户自己定义的函数,用来扩展

OSTaskCreateExt()的功能。OSTaskCreateHook()可以在OS_CPU_C.C中定义(如果

OS_CPU_HOOKS_EN置1),也可以在其它地方定义(如果OS_CPU_HOOKS_EN置0)。注意,

OSTaskCreateExt()在调用OSTaskCreateHook()时,中断是关掉的,所以用户应该使

OSTaskCreateHook()函数中的代码尽量简化,因为这将直接影响中断的响应时间。

OSTaskCreateHook()被调用时会收到指向任务被建立时的OS_TCB的指针。这意味着该函数可以访问OS_TCB数据结构中的所有成员。

如果OSTaskCreateExt()函数是在某个任务的执行过程中被调用的(即OSRunning置为

True[L4.3(11)]),以任务调度函数会被调用[L4.3(12)]来判断是否新建立的任务比原来的任务有更高的优先级。如果新任务的优先级更高,内核会进行一次从旧任务到新任务的任务切换。如果在多任务调度开始之前(即用户还没有调用OSStart()),新任务就已经建立了,则任务调度函数不会被调用。

4.2任务堆栈

每个任务都有自己的堆栈空间。堆栈必须声明为OS_STK类型,并且由连续的内存空间组成。用户可以静态分配堆栈空间(在编译的时候分配)也可以动态地分配堆栈空间(在运行的时候分配)。静态堆栈声明如程序清单L4.4和4.5所示,这两种声明应放置在函数的外面。

程序清单 L4.4 静态堆栈

staticOS_STKMyTaskStack[stack_size];

程序清单 L4.5 静态堆栈

OS_STKMyTaskStack[stack_size];

用户可以用C编译器提供的malloc()函数来动态地分配堆栈空间,如程序清单L4.6所示。在动态分配中,用户要时刻注意内存碎片问题。特别是当用户反复地建立和删除任务时,内存堆中可能会出现大量的内存碎片,导致没有足够大的一块连续内存区域可用作任务堆栈,这时malloc()便无法成功地为任务分配堆栈空间。

程序清单 LL4.6 用malloc()为任务分配堆栈空间

OS_STK*pstk;

pstk=(OS_STK*)malloc(stack_size);

if(pstk!=(OS_STK*)0){/* 确认malloc()能得到足够地内存空间 */

Createthetask;

}

图4.1表示了一块能被malloc()动态分配的3K字节的内存堆[F4.1(1)]。为了讨论问题方便,假定用户要建立三个任务(任务A,B和C),每个任务需要1K字节的空间。设第一个1K字节给任务A,第二个1K字节给任务B,第三个1K字节给任务C[F4.1(2)]。然后,用户的应用程序删除任务A和任务C,用free()函数释放内存到内存堆中[F4.1(3)]。现在,用户的内存堆虽有2K字节的自由内存空间,但它是不连续的,所以用户不能建立另一个需要2K字节内存的任务(即任务D)。如果用户并不会去删除任务,使用malloc()是非常可行的。



关键词:

评论


相关推荐

技术专区

关闭