操作系统栈溢出检测之uc/osII篇
Author : David Lin (林鹏)
E-mail : linpeng1577@gmail.com linpeng1577@163.com 15820224344@163.com
OS : 源码级理解掌握Ucos,Rt-thread等嵌入式操作系统内核的设计与实现,目前在研究linux内核,路漫漫其修远兮,吾将上下而求索 :)
转载请注明出处,谢谢
前言:
在嵌入式操作系统运行中,进程的栈溢出问题是大家比较关心的问题,由于资源限制,栈大小受到限制,本文主要介绍uc/os自带的栈检测机制(为什么是ucos,而不是ecos或者其他,因为我现在项目用这个,后续有时间再介绍一种更简单通用,不依赖具体操作系统的栈溢出检测机制)。
原理:
1.在进程的栈初始化的时候,按预设的字节对齐方式,用特定魔数(比如0x9527,ucosII预设是0值)将栈元素依次完成初始化;
2.在系统运行的时候,通过守护进程,依次遍历各个进程的栈,检测栈元素的值是否等于初始化的魔数,求得被污染的元素个数所占栈大小的比例,即为栈使用量。
3.不通过守护进程,直接对进程进行栈溢出检测是否可行?可以,不过不推荐在进程内部或者进程调度的时候进行如此使用量检测,即使使用二分查找算法进行优化,如果栈大到一定程度,效 率问题还是需要慎重考虑的;
4.不扯为什么这么设计这些事情了,这跟小学语文写作者的中心思想一样,不是ucos原作者,所以不写,你想知道Jean J. Labrosse怎么想的,可以给他发邮件:-)
系统版本:uc/osII V2.85
开发环境:IAR for ARM (为什么不在linux下开发,我也想知道,
因为我喜欢gnu/linux,喜欢用gcc,gdb,vim,make,(⊙o⊙)…,不过,你懂的:-)
1. 相关宏定义os_cfg.h
#defineOS_TASK_STAT_EN 1 /* Enable (1) or Disable(0) the statistics task*/
#defineOS_TASK_STAT_STK_CHK_EN 1 /* Check task stacks from statistic task */
2. 相关函数os_core.c os_task.c
static void OS_InitTaskStat (void) {……}; //初始化栈守护进程,看哪个进程最贪吃 :-)
/*
*********************************************************************************************************
* INITIALIZATION
* CREATING THE STATISTIC TASK
*
* Description: This function creates the Statistic Task.
*
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
#if OS_TASK_STAT_EN > 0
static void OS_InitTaskStat (void)
{
#if OS_TASK_NAME_SIZE > 7
INT8U err;
#endif
#if OS_TASK_CREATE_EXT_EN > 0
#if OS_STK_GROWTH == 1
(void)OSTaskCreateExt(OS_TaskStat,
(void *)0, /* No args passed to OS_TaskStat()*/
&OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], /* Set Top-Of-Stack */
OS_TASK_STAT_PRIO, /* One higher than the idle task */
OS_TASK_STAT_ID,
&OSTaskStatStk[0], /* Set Bottom-Of-Stack */
OS_TASK_STAT_STK_SIZE,
(void *)0, /* No TCB extension */
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */
#else
(void)OSTaskCreateExt(OS_TaskStat,
(void *)0, /* No args passed to OS_TaskStat()*/
&OSTaskStatStk[0], /* Set Top-Of-Stack */
OS_TASK_STAT_PRIO, /* One higher than the idle task */
OS_TASK_STAT_ID,
&OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], /* Set Bottom-Of-Stack */
OS_TASK_STAT_STK_SIZE,
(void *)0, /* No TCB extension */
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */
#endif
#else
#if OS_STK_GROWTH == 1
(void)OSTaskCreate(OS_