【RT-Thread】使用 Finsh 查看线程状态中的 sp 代表什么意思?

291 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

佛说:“一切有为法,如梦幻泡影,如露亦如电,应作如是观。” --《金刚经》

详解 sp 含义

最近使用 RT-ThreadFinsh 输入 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

可以看到 tidlemain 线程的 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_sizethread->stack_addr 一旦初始化后是不变的。 再看看上述代码,我们可以知道此处的 sp 并不是指的是线程栈指针(应是 thread->sp),而是指的是相对于栈底的位置的距离。 这里假设所有线程的栈底地址都是 0x00000000,则对于上文中的 main 线程的 sp(0x00000040)的值则是相对于栈顶值的距离为 0x00000040

总结来说 Finsh 打印出的 sp 值代表的是一个相对于栈底的值,含义是线程指针 thread->sp 距离栈底的距离。由于是相对的,所以会出现很多线程在这一项上相同也是正常的,并不是出现了什么异常?

sp 这一项内容之所以没有选择使用绝对地址其实是合理的,因为假设显示的是绝对地址,你从这个地址得到的信息量非常少,这一串地址无法推出当前堆栈的使用情况(除非你查看栈底位置,那么你就需要找到代码,还要查看map文件找到其具体地址,如果是动态初始化的线程更麻烦),而使用相对地址,则很好地展现了当前栈的使用量情况。

参考资料