1252_FreeRTOS_堆栈溢出检查方法与测试

全部学习汇总: GreyZhang/g_FreeRTOS: learning notes about FreeRTOS. (github.com)

参考API这次先不看,先从堆栈溢出的角度看一下。开启这个功能需要配置configCHECK_FOR_STACK_OVERFLOW这个参数。如果这个参数不为0的时候,就要提供上面的hook函数。这里写得是不为0,不知道是非零有多种含义还是含义全都相同呢?

堆栈的检查功能肯定会增加上下文切换的负载率,因此推荐在开发和测试的时候使用,产品中这个功能不要开启。

前面刚刚出现的疑问在这里接着找到了答案,configCHECK_FOR_STACK_OVERFLOW的配置不同的数值是有不同含义的。从上面的信息,结合FreeRTOS可以提供两种堆栈检查方法可以知道这个参数可以有3种数值选择。结合下面的信息,参数值可以是0、1、2。

回到针对第一个方法的梳理。堆栈的检查一般是在OS完成了上下文切换之后,因为这个时候由于现场保护,上下文的信息需要存储到任务堆栈之中。此时的系统可能有着最大的任务stack消耗。这个时候,查一下stack指针是否有超出最大边界的情况就可以知道是否有stack的溢出了。

优点:快!

缺点:出现问题不一定百分百全都可以捕捉到。

第二个方法,使用的时候配置参数需要设置为2。当任务从运行状态切换出去的时候,检查堆栈的情况。检查的方法是检查存储信息,这样就需要在任务创建的时候在任务stack中填充固定的已知数据。之后检查的时候检查任务stack最后的16个字节。

优点: 检查可靠性高,但是也不是百分之百。

缺点:比第一种方法慢,但是也不是很慢。

之前,看过一点RT-Thread的代码,看到了任务stack初始化的时候填充了DEADBEAF。可能也是要完成类似的功能,16个字节就是2组DEADBEAF。

这是之前运行过的QEMU的例程,在FreeRTOS.h中有这样的信息。也就是说,如果不增加配置的话,默认会不启用这个检查功能。一般,OS的类似的功能配置都是在FreeRTOSConfig.h中。而FreeRTOS.h包含了这个头文件,因此如果有定义的话,第一段预处理的代码就不会展开。

以上,是现在用户代码中的配置信息。

main.c中有检查hook函数的定义。接下来,注释掉这段代码,看看编译是否报错。按照前面的说明,现在的这个函数是必须要提供的。

实际的测试跟描述是相符的,也就是说现在的这个示范工程中这个检查功能是生效的。修改配置值为1,也是一样的效果。当修改成0的时候,编译链接通过。

查看了一下,这个检查所用的hook在stack_macros.h中定义的。根据我现在的工程配置,方法选择2,以上是生效的代码。判断的条件有2个,一个是检查的方法,另一个是stack增长的方向。这里,刚刚是检查了4个32bit的数据,也就是16个字节。按照4字节检查其是否是0xa5a5a5a5。

如果stack的增长方向相反,那么检查是按照字节来处理的。检查的效果其实是一样的,但是按照增长顺序检查,可以便捷使用库函数。

设计上面的测试代码,在RX的任务中调用。

以上是增加的测试代码调用。为了能够让测试时间短一些,我修改了几个时间相关的参数。接下来,测试两种stack溢出检查的效果。

这是使用方法1检测的时候出现的提示,感觉stack的溢出没有检查到。

最终停在了上图中的3033,为了找到触发原因,增加了2个printf。

看了一下打印的log,其实这个接口只有这里调用了一次。

这是上面的两个信息的解释,从解释看的话,这个数值肯定是错误的,绝对不会这么大。可能的原因是存储异常,而stack溢出很可能是其中的一个原因。

加入了类似上面的信息,捕捉到了在哪个接口出现的问题。

这么看,就是前面截图的代码中出现了问题。

进一步,找到了这里,看起来可能是发送队列信号的时候出现了异常。但是,异常肯定是发送之前产生的。那么,按照这个软件的执行规律,肯定是前面的Timer发送了队列信号,触发了计算后导致了stack异常。接下来,进行新的周期性调度发送发现内存异常。这个能够解释的清楚,但是也看得出来这个stack的溢出检测并不准确。

接下来,看看第二种堆栈溢出的测试。

当使用第二种堆栈溢出的检查方法的时候,成功找到了堆栈溢出的任务。这么看,第二种方式的确是准确一些。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值