在Zephyr中每个线程的堆栈大小在创建时就已经指定,运行过程中无法再做改变,线程运行的上下文是存放在线程的堆栈中,一旦堆栈被破坏意味着线程的执行上下文被破坏,这将导致线程执行出现不可预期的异常,Zephyr针对可能造成线程破坏的情况提供了保护,监控,预防手段。本文将介绍比较通用的一些堆栈保护技术,这些技术除了在Zephyr上出现外,其它OS也广泛的采用了这些技术。
Zephyr线程堆栈结构
Zephyr使用K_THREAD_STACK_DEFINE创建的线程堆栈,所有的线程堆栈会在内存中依次放在noinit段内。如下图所示
Zephyr创建了A~E五个线程相邻而放,在一个线程堆栈内函数调用会占用堆栈,诸如局部变量,传递参数等会放到堆栈内,上图函数调用关系是Fun1调用Fun2,Fuc2调用Fun3。一般情况下堆栈的生长方向是由高地址向低地址(也有特殊的体系架构是反着的),本文只讨论高向低生长的情况。基于以上的堆栈结构,堆栈可能出现下面2个问题:
问题1. 线程中调用的函数层级过深,或者某个函数需要的堆栈很大,会导致堆栈增长超过线程分配的堆栈而写到其它线程堆栈中,例如线程C中Fun3继续调用其它函数一层层下去,堆栈会增长超过C的stack而进入到B中,把B写坏。
问题2. 函数操作局部变量发生溢出写过局