详解 sp 含义
最近使用 RT-Thread 的 Finsh 输入 list_thread 命令查看线程状态时,突然注意到多个线程在 sp 这一项内容上竟然是相同的,如下所示:
thread pri status sp stack size max used left tick error
tidle 31 ready 0x00000040 0x00000100 25% 0x00000020 000
timer 4 suspend 0x00000044 0x00000200 29% 0x00000009 000
main 10 running 0x00000040 0x00000800 03% 0x00000014 000
可以看到 tidle 和 main 线程的 sp 这一项是相同的,再来看看官方对于这一项的描述:
所以就有些疑惑了,RT-Thread 的线程是拥有自己独立的线程栈的,这就意味着不应该出现上文的栈地址相同的情况,既然这样,我们一探源码看看,老实的代码可不会骗人。
在 cmd.c 文件中的 list_thread 函数中找到 sp 选项对应的实现如下(仅保留相关代码):
#if defined(ARCH_CPU_STACK_GROWS_UPWARD)//向上增长的栈
((rt_ubase_t)thread->sp - (rt_ubase_t)thread->stack_addr), //sp的值
#else //向下增长的栈,Cortex-M 系列属于这种
thread->stack_size + ((rt_ubase_t)thread->stack_addr - (rt_ubase_t)thread->sp), //sp的值
#endif
首先需要说明的是,对于 thread->stack_size 和 thread->stack_addr 一旦初始化后是不变的。 再看看上述代码,我们可以知道此处的 sp 并不是指的是线程栈指针(应是 thread->sp),而是指的是相对于栈底的位置的距离。 这里假设所有线程的栈底地址都是 0x00000000,则对于上文中的 main 线程的 sp(0x00000040)的值则是相对于栈顶值的距离为 0x00000040。
总结来说 Finsh 打印出的 sp 值代表的是一个相对于栈底的值,含义是线程指针 thread->sp 距离栈底的距离。由于是相对的,所以会出现很多线程在这一项上相同也是正常的,并不是出现了什么异常?
sp 这一项内容之所以没有选择使用绝对地址其实是合理的,因为假设显示的是绝对地址,你从这个地址得到的信息量非常少,这一串地址无法推出当前堆栈的使用情况(除非你查看栈底位置,那么你就需要找到代码,还要查看map文件找到其具体地址,如果是动态初始化的线程更麻烦),而使用相对地址,则很好地展现了当前栈的使用量情况。
原作者:Eureka1024
|