一、什么是线程?
线程是系统调度的最小单位,通俗地说,它是一个“正在执行的函数”或者“被暂停的代码执行流”。
线程的三要素
函数入口:线程的起始地址。
栈(Stack):用于存储局部变量、返回地址等。
线程控制块(Thread Control Block,TCB):
保存线程当前状态(运行、就绪、挂起等)
包含栈顶指针、优先级、线程名、时间片等信息
二、线程切换的本质:保存与恢复上下文
当系统在多线程之间切换时,必须确保线程上下文能够完整恢复。
什么是“现场”?
“现场”指的是当前线程在某一时间点下的 CPU 状态,包括寄存器、栈指针等信息。
不需要保存的内容:
全局变量:保存在内存中,线程共享,无需特殊处理。
局部变量:保存在栈中,栈指针恢复后也随之恢复。
需要保存的内容:
CPU 所有寄存器:
通用寄存器(R0 ~ R12)
链接寄存器(R14,LR)
程序计数器(PC)
栈指针(SP)
程序状态寄存器(xPSR)
三、汇编视角下的线程上下文
常见汇编指令理解
四、线程上下文切换过程详解
保存现场
切换线程前,必须将当前线程的 CPU 状态保存到线程的栈中。过程如下:
使用 PUSH 将 R0 ~ R12、LR(R14)、xPSR 等寄存器入栈。
更新线程控制块中的栈顶指针信息。
恢复现场
当某线程被重新调度执行:
从 TCB 读取保存的栈顶地址。
使用 POP 将寄存器信息恢复到 CPU。
跳转回程序计数器(PC)对应的执行地址,线程继续运行。
这整个过程在 RT-Thread 的调度器中由汇编代码或汇编辅助的 C 代码完成。
五、线程的栈空间与 CPU 的栈机制
在单线程系统中,程序只需要一个栈即可运行。但在 RT-Thread 这类多线程系统中,每个线程都拥有独立的栈空间,用于保存其局部变量、函数返回地址、上下文等。
CPU 里有多个栈吗?
并不是 CPU 里存在多个“实体栈”,而是通过切换 栈指针(SP) 来访问 内存中不同的栈空间。
多线程下的栈切换机制:
每个线程创建时,在内存中会被分配一块独立的栈空间。
每当发生线程切换:
当前线程的栈指针 SP 被保存到其控制块(TCB)中。
下一个线程的 TCB 中的 SP 被加载到 CPU 的 SP 寄存器中。
这样,虽然 CPU 只有一个 SP 寄存器,但通过切换指针实现了对多个栈的管理。
线程切换的本质就是:改变 CPU 的堆栈指针(SP)指向不同的线程栈空间。
每个线程都有自己独立的一块栈空间。
CPU 切换线程时,只需要:
保存当前线程的 CPU 上下文到自己的栈中;
更新当前线程控制块(TCB)里的 SP 值;
加载下一个线程的 SP;
从新线程的栈中恢复 CPU 上下文。
Cortex-M 特性:双栈指针
RT-Thread 会配置线程使用 PSP,而中断使用 MSP,实现线程和系统中断的栈分离。
六、动态线程与静态线程的区别
RT-Thread 中的线程可以通过两种方式创建:静态创建 和 动态创建。
静态线程(Static Thread)
在线程创建前,由用户手动定义好栈空间和控制块;
使用 rt_thread_init() 函数初始化;
内存由用户分配,不经过 RT-Thread 的内存管理器;
生命周期完全由开发者控制(比如放在全局变量中)。
static struct rt_thread thread1;
static char thread1_stack[512];
rt_thread_init(&thread1,
"thread1",
thread1_entry,
RT_NULL,
&thread1_stack[0],
sizeof(thread1_stack),
5, 20);
rt_thread_startup(&thread1);
适用场景:
对内存分配更可控(比如裸机环境);
对堆空间有限制的嵌入式系统;
系统启动时常驻线程。
动态线程(Dynamic Thread)
通过 RT-Thread 内存管理器动态申请 TCB 和栈空间;
使用 rt_thread_create() 创建;
不需要用户提前分配内存;
生命周期由 RT-Thread 管理。
rt_thread_t tid = rt_thread_create("thread2",
thread2_entry,
RT_NULL,
512,
10, 10);
if (tid != RT_NULL)
rt_thread_startup(tid);
适用场景:
对资源自动管理需求高;
灵活创建/删除线程;
系统资源允许时优选方式。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/hallo_zz/article/details/147516457
|