2. 线程动态创建与静态创建
任务目标
在RT-Thread中,线程有两种创建方式:动态创建(rt_thread_create)和静态初始化(rt_thread_init)。两者的核心区别在于线程控制块和线程栈的内存来源:动态创建由系统从堆中自动分配,静态初始化则需要用户预先定义并传入。本案例分别用两种方式创建两个线程,通过串口输出验证它们都能独立运行,并直观理解静态线程的内存分配方式。
核心实现
动态创建使用rt_thread_create(),只需传入入口函数、参数、栈大小等参数,系统内部完成struct rt_thread和栈空间的堆分配。静态初始化使用rt_thread_init(),需要用户预先定义static struct rt_thread线程控制块和static rt_uint8_t栈数组,初始化后通过rt_thread_startup()启动。两种方式启动后的调度行为完全一致。
运行与验证
编译与下载:本案例基于RT-Thread Studio或Env环境,在任意支持RT-Thread的BSP工程中新建main.c并粘贴上述代码,编译后下载至开发板。
预期串口输出:系统启动后,两个线程交替打印(调度顺序由优先级决定,动态线程优先级20略高,会先运行):
dynamic is running, count = 0
static is running, count = 0
dynamic is running, count = 1
static is running, count = 1
...
通过条件:串口终端能看到dynamic和static两个线程各自循环打印且计数递增,说明两种创建方式均成功运行。若只出现一个线程的输出,检查另一个线程的优先级是否被占用或栈大小是否不足。
关键区别说明
| 对比项 | 动态创建 | 静态初始化 |
|---|---|---|
| API | rt_thread_create() | rt_thread_init() |
| 控制块来源 | 堆(rt_malloc) | 用户定义的全局变量 |
| 栈来源 | 堆(rt_malloc) | 用户定义的全局数组 |
| 释放方式 | rt_thread_delete() | rt_thread_detach() |
| 适用场景 | 线程数量/栈大小运行时才确定 | 资源固定、避免堆碎片 |
内存理解要点:静态线程的
static_thread控制块和static_thread_stack[512]数组都位于全局数据区(.bss段),在编译链接时地址已确定,不占用堆空间。动态线程的dynamic_thread指针本身在栈上,但它指向的struct rt_thread和512字节栈均在堆中分配。观察rt_thread_init的参数——需要显式传入控制块地址和栈地址,这正是静态方式“内存由用户提供”的体现。
常见问题
- 静态线程初始化失败:检查传入的栈地址是否8字节对齐(RT-Thread要求栈起始地址对齐),以及控制块是否重复初始化。
- 动态创建返回RT_NULL:通常是堆空间不足,可调大
HEAP_SIZE或改用静态方式。 - 两个线程只有一个运行:确认两个线程优先级不同(本案例为20和21),相同优先级时需依赖时间片轮转,且两个线程都需在循环中主动让出CPU(如
rt_thread_mdelay)。