分类:
2009-06-04 16:42:11
----------------------------------------------------
本文系本站原创,欢迎转载!
转载请注明出处:http://dreamlcr.cublog.cn/
----------------------------------------------------
任务堆栈
每个任务都有自己的堆栈空间。堆栈必须声明为OS_STK类型,并且由连续的内存空间组成。可以静态分配堆栈空间(在编译时分配),也可以动态分配堆栈空间(在运行时分配)。静态堆栈声明如以下程序清单所示,这两种声明都应放置在函数的外面。
静态堆栈
static OS_STK MyTaskStack[stack_size];
或
OS_STK MyTaskStack[stack_size];
用户可以用C编译器提供的malloc()函数来动态地分配堆栈空间,如以下程序清单所列。在动态分配中,要时刻注意内存碎片问题。特别是当反复地建立和删除任务时,内存堆中可能会出现大量的内存碎片,导致没有足够大的一块连续内存区域可用作任务堆栈,这时malloc()便无法成功地为任务分配堆栈空间。
用malloc()为任务分配堆栈空间
OS_STK *pstk;
pstk = (OS_STK *)malloc(stack_size);
if (pstk != (OS_STK *)0) { /* 确认malloc()能得到足够的内存空间 */
Create the task;
}
下图表示了一块能被malloc()动态分配的3KB的内存碎片。
F(1)为了讨论问题方便,假定要建立三个任务(任务A,B和C),每个任务需要1KB字节的空间。
F(2)设第一个1KB给任务A,第二个1KB给任务B,第三个1KB给任务C。
F(3)应用程序删除任务A和任务C,用free()函数释放内存到内存堆中。现在,内存堆虽有2KB的自由内存空间,但却是不连续的,所以不能建立另一个需要2KB内存的任务(任务D)。但是,如果从未删除任何任务,那么使用malloc()分配内存空间就是可行的。
uC/OS-II支持的处理器的堆栈既可以是递减的,也可以是递增的。在调用函数OSTaskCreate()或OSTaskCreateExt()时,必须知道堆栈是递减的,还是递增的,因为用户必须把堆栈的栈顶地址传递给以上这两个函数。当OS_CPU.H文件中的OS_STK_GROWTH置为0时,需要将堆栈的最低内存地址传递给任务创建函数,如以下程序清单所示。
堆栈从下往上递增
OS_STK TaskStack[TASK_STACK_SIZE];
OSTaskCreate(task, pdata, &TaskStack[0], prio);
当OS_CPU.H文件中的OS_STK_GROWTH置为1时,需要将堆栈的最高内存地址传递给任务创建函数,如以下程序清单所示。
堆栈从上往下递减
OS_STK TaskStack[TASK_STACK_SIZE];
OSTaskCreate(task, pdata, &TaskStack[TASK_STACK_SIZE-1], prio);
这个问题会影响代码的可移植性。如果想将代码从支持往下递减堆栈的处理器中移植到支持往上递增堆栈的处理器中,需使代码同时适应以上两种情况。在这种特殊情况下,以上的两个程序清单可重新写成如下程序清单所列的形式。
对两个方向增长的堆栈都提供支持
OS_STK TaskStack[TASK_STACK_SIZE];
#if OS_STK_GROWTH == 0
OSTaskCreate(task, pdata, &TaskStack[0], prio);
#else
OSTaskCreate(task, pdata, &TaskStack[TASK_STACK_SIZE-1], prio);
#endif
任务所需的堆栈的容量是由应用程序指定的。在确定堆栈容量时,必须考虑到任务调用的所有函数的嵌套情况、任务调用的所有函数为局部变量分配的所有内存的数目,以及所有可能的中断服务子程序嵌套对堆栈的需求。另外,堆栈必须能保存CPU所有的寄存器。