中的256是堆栈空间。
这个堆栈是线程切换时保存现场用的吗?还是线程体中所用堆栈的大小。
如果是前者,那么即使线程体中用的堆栈大小超过256,也不会影响线程运行吧?
栈 - Stack
堆 - Heap
它们是完全不同的概念。
1.普通前后台系统
main函数的while(1)属于后台,isr属于前台。
在主循环中调用函数完成具体功能,发生中断,从主循环中切换到isr,处理完毕回到主循环。整个过程只有一个栈。我们不妨将它称之为Main Stack
。
一般写函数,形参个数不超过4个,此时通过R0 ~ R3传递函数参数;如果形参超过4个,则使用栈传递参数。函数内部的临时变量,从栈中分配。
一段伪代码:
main.c
2.RTOS
假设有2个线程。
系统启动,从启动代码中开始运行,直到进入到高优先级线程中,使用Main Stack
。
进入高优先级线程,使用该线程的栈,我们称之为Process Stack
,即你帖子中提到的256
字节的Stack。在thread_entry中进行函数调用的开销,都在这256字节的栈中完成。
由于有2个线程,所以RTOS下的Stack合计为:
Main Stack Size + Thread1 Process Stack Size + Thread2 Process Stack Size
Q:
如果是前者,那么即使线程体中用的堆栈大小超过256,也不会影响线程运行吧?
A:
线程中的栈是用来做现场保护的。线程中的堆和栈是两个不同的概念,你可看前文的伪代码中的注释。
如果线程中,函数调用深度较深,如
而每个函数中都用了128字节的临时变量,所需要的栈远超过了256字节,导致栈溢出,可能破坏了其他线程的栈,可能导致某些变量的值异常,线程大概率就死掉了,一定会影响线程运行。
单个线程栈消耗,记得还要算上线程上下文。
@aozima
嗯嗯,更严谨。但是想着从面上和lz说明一下区别,这部分就忽略掉了。
编辑确认一下,您是指进入线程前的r0-r15以及fpu register这部分的开销吗?@aozima
请问一下这个公式
Main Stack Size + Thread1 Process Stack Size + Thread2 Process Stack Size
线程栈不是从main栈里分出来的吗?
比如主栈是0x0400,线程栈是声明的数组,应该是在主栈里边啊,Main Stack Size包含Thread1 Process Stack Size + Thread2 Process Stack Size
@伊森亨特
以Cortex-m3/m4等单核处理器为例:
我的回帖中,Main Stack指的是MSP指向的栈,而不是main线程的栈。
如果使用rt_thread_create函数,则线程的栈是从Heap中分配的,运行时动态分配;
如果使用rt_thread_init函数,则线程的栈是从.bss/.data中分配的,且这部分在编译的时候就确定了。
线程的栈指针是PSP。
Stack_Size EQU 0x00000400
然后我静态创建线程栈大小0x1000,会出问题吗?0x400和0x1000有什么关系吗?@lchnu
@FKXZ_3628
请看如下两个帖子的内容:
链接文件.lds内的栈大小,和rt-thraed 中的为main线程分配的栈大小有关系吗?
https://club.rt-thread.org/ask/question/21f4e75199f77f7f.html
我的一篇短文,RT-Thread从启动到进入第一个线程的过程:
https://club.rt-thread.org/ask/article/2493d824711da9a2.html
对你问题的直接回复:
你提到的Stack_Size为0x400,对应MSP。
静态创建线程,栈大小是0x1000,表示你使用了一个如下的数组,作为线程的栈。线程栈在运行的时候,对应PSP。
因此,问题中0x400和0x1000没有任何关系。
以STM32的Cortex M3/4系列为例,MSP和PSP对应同一个sp寄存器,根据处理器的模式不同自动切换。