【RTOS】FreeRTOS中的任务堆栈溢出检测机制
前言
注意:本笔记发布时可能忘记补充查看dump方法,可使用TRACE32来查看dump时的各个任务信息,方便分析。
李柱明博客:https://www.cnblogs.com/lizhuming/p/15487221.html
任务堆栈
在 FreeRTOS 中,每个任务都拥有自己的堆栈,该堆栈的大小由创建任务时 xTaskCreate 函数的函数参数所决定。
堆栈溢出
当任务所使用的堆栈空间超出分配给它的空间时,则会发生堆栈溢出。
堆栈溢出可能修改超过合法访问地址范围外的数据,严重时会导致 Hardfault 令系统崩溃。
任务堆栈溢出检测机制
API
在 FreeRTOS 中,也提供了一些 API 函数用来检测任务堆栈的使用情况:
-
uxTaskGetStackHighWaterMark (TaskHandle_t xTask);
:- 返回自任务运行以来剩余可用堆栈空间的最小值。
- 开启方法:在 FreeRTOSConfig.h 头文件中使能宏:
#define INCLUDE_uxTaskGetStackHighWaterMark 1
两种堆栈溢出检测方式
-
方式 1:
- 开启方法:
#define configCHECK_FOR_STACK_OVERFLOW 1
- 在任务切换是检测任务栈指针是否越界,如果越界,在任务切换的时候触发堆栈溢出钩子函数。
- 开启方法:
-
方式 2:
- 开启方法:
#define configCHECK_FOR_STACK_OVERFLOW 2
- 在任务创建的时候将任务栈所有数据初始化为 0xA5,在任务切换时检测任务栈底 16 个字节是否都为 0xa5。
- 开启方法:
堆栈溢出钩子函数
void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName)
{
// 溢出后的操作
}
内核何时检测任务堆栈溢出
任务上下文切换的时候做检测:
- 代码说明:因为在 FreeRTOS 源码 tasks.c 文件中可以查到 taskCHECK_FOR_STACK_OVERFLOW 在 void vTaskSwitchContext( void )函数中被调用了。
- 滞后性:任务堆栈溢出时并不能马上检测到问题,因为任务堆栈溢出在任务上下文切换的时候才做检测。
任务堆栈溢出检测存在的局限性
根据两种方式的原理及执行任务堆栈溢出的位置得出包括但不限于以下情境会检测不到任务堆栈溢出:
-
任务执行的过程中出现过栈溢出,但任务切换前栈指针又恢复到了正常水平。(方式 1)
-
任务栈末尾的 16 个字节没有用到,即不会被修改,但是任务栈已经溢出了。(方式 2)
-
任务栈溢出后,把系统中的重要数据修改了导致系统直接进入 Hardfault。(方式 1、2)
- 该方式进入了 Hardfault,就不能直接判断是任务堆栈溢出的问题。
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现