(二)RT-Thread线程管理全解析
RT-Thread线程管理全解析 — 创建、调度与生命周期
前言
线程是RT-Thread中最小的调度单位,理解线程管理是掌握RTOS的基础。本文将详细介绍线程的概念、状态转换、优先级机制以及创建和调度方法,并通过代码实例帮助你快速上手。
一、线程的概念
可以把多线程系统想象成一个繁忙的工厂:工人(线程)各自负责特定任务,调度员(调度器)负责分配工作,确保最重要的任务优先完成。
在 RT-Thread 中,线程是最小的工作单元。你可以将一个大任务拆分成多个线程,各自负责不同部分(如读取传感器、更新显示屏),系统根据优先级自动调度。
二、线程的组成部分
每个线程由三个核心部分组成:
| 组成部分 | 说明 | 比喻 |
|---|---|---|
| 线程控制块 | 记录线程名字、优先级、状态等信息 | 工人的身份证 |
| 线程栈 | 保存线程执行过程中的临时数据 | 工人的工具箱 |
| 入口函数 | 定义线程具体要做什么 | 工人的任务说明书 |
三、线程的状态
线程有五种状态:
| 状态 | 说明 |
|---|---|
| 初始状态 | 线程刚创建,尚未开始运行 |
| 就绪状态 | 准备好执行,等待调度器分配CPU |
| 运行状态 | 正在使用CPU执行任务 |
| 挂起状态 | 暂停执行,等待资源或事件(如定时器到期、信号量释放) |
| 关闭状态 | 任务完成或被删除,线程生命周期结束 |
状态转换路径:初始 → 就绪 → 运行 ↔ 挂起 → 关闭
四、线程优先级
RT-Thread 支持 256 个优先级(0-255),数字越小优先级越高。0 为最高优先级,系统空闲线程分配最低优先级。
调度规则:
- 调度器总是选择优先级最高的就绪线程运行。
- 高优先级线程可以抢占低优先级线程(全抢占式调度)。
可通过配置将优先级数量裁剪为 32 或 8 个,以节省资源。
五、时间片
当多个线程具有相同优先级时,系统使用时间片轮转机制:每个线程分配固定的时间片,轮流执行。
例如:线程 A 时间片为 10,线程 B 时间片为 5,则 A 执行 10 个时间单位后切换到 B,B 执行 5 个时间单位后再切换回 A。
六、创建线程:rt_thread_create
6.1 函数原型
rt_thread_t rt_thread_create(const char *name,
void (*entry)(void *parameter),
void *parameter,
rt_uint32_t stack_size,
rt_uint8_t priority,
rt_uint32_t tick);
6.2 参数说明
| 参数 | 说明 | 示例 |
|---|---|---|
name |
线程名称,用于调试标识 | "led_ctrl" |
entry |
入口函数,线程具体执行的逻辑 | led_thread_entry |
parameter |
传递给入口函数的参数 | RT_NULL(无参数) |
stack_size |
线程栈大小(字节)。简单任务512,复杂任务1024+ | 512 |
priority |
优先级,0最高,数值越大越低 | 25 |
tick |
时间片大小,仅在同优先级线程间生效 | 5 |
6.3 基础示例
#include <rtthread.h>
static rt_thread_t tid1 = RT_NULL;
static void thread1_entry(void *parameter)
{
int count = 0;
while (1)
{
rt_kprintf("Thread 1 is running, count: %d\n", count);
count++;
rt_thread_mdelay(1000); // 休息1秒
}
}
int main(void)
{
tid1 = rt_thread_create("thread1",
thread1_entry, RT_NULL,
1024, 20, 10);
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
return 0;
}
6.4 LED 控制线程示例
#include <rtthread.h>
#define LED_STACK_SIZE 512
#define LED_PRIORITY 25
#define LED_TICK 5
void led_thread_entry(void *parameter)
{
rt_kprintf("LED Thread Running...\n");
while (1)
{
rt_pin_write(LED_PIN, PIN_HIGH); // 点亮LED
rt_thread_mdelay(500);
rt_pin_write(LED_PIN, PIN_LOW); // 熄灭LED
rt_thread_mdelay(500);
}
}
int main(void)
{
rt_thread_t led_thread = rt_thread_create("led_ctrl",
led_thread_entry,
RT_NULL,
LED_STACK_SIZE,
LED_PRIORITY,
LED_TICK);
if (led_thread != RT_NULL)
rt_thread_startup(led_thread);
return 0;
}
七、rt_thread_mdelay vs 普通 delay
这是从裸机开发迁移到RTOS时最重要的认知转变之一。
7.1 核心区别
| 区别点 | rt_thread_mdelay |
普通 delay_ms |
|---|---|---|
| 是否释放CPU | 是,线程进入挂起状态 | 否,CPU忙等待 |
| 系统调度 | 支持多线程调度和切换 | 无法调度其他任务 |
| 功耗管理 | 可进入低功耗模式 | CPU一直忙等待 |
| 适用环境 | 多线程RTOS环境 | 单任务裸机环境 |
7.2 通俗理解
- 普通
delay:在咖啡店柜台前干等,什么都不做,浪费时间。 rt_thread_mdelay:排队时先去做别的事情,等时间到了再回来,不浪费时间。
7.3 工作机制
rt_thread_mdelay 的调用流程:
- 当前线程进入
RT_THREAD_SUSPEND(挂起状态) - 调度器切换到其他就绪线程执行
- 延时结束后,线程恢复为就绪状态,等待调度
关键原则:在RTOS环境中,永远不要使用忙等待的delay,应使用
rt_thread_mdelay让出CPU资源。
八、线程调度与空闲线程
8.1 调度机制
调度器始终选择优先级最高的就绪线程执行。当高优先级线程完成任务或主动让出CPU时,调度器切换到下一个就绪线程。
8.2 空闲线程
空闲线程是优先级最低的系统线程,在没有其他任务运行时执行,负责:
- 回收已完成线程的资源
- 执行用户注册的空闲钩子函数
九、实战:多线程交替执行
#include <rtthread.h>
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 1024
#define THREAD_TIMESLICE 5
static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;
static void thread1_entry(void *parameter)
{
int count = 0;
while (count < 10)
{
rt_kprintf("Thread 1 is running, count: %d\n", count);
count++;
rt_thread_mdelay(1000);
}
}
static void thread2_entry(void *parameter)
{
int count = 0;
while (count < 10)
{
rt_kprintf("Thread 2 is running, count: %d\n", count);
count++;
rt_thread_mdelay(1000);
}
}
int main(void)
{
tid1 = rt_thread_create("thread1",
thread1_entry, RT_NULL,
THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
tid2 = rt_thread_create("thread2",
thread2_entry, RT_NULL,
THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
if (tid1 != RT_NULL) rt_thread_startup(tid1);
if (tid2 != RT_NULL) rt_thread_startup(tid2);
return 0;
}
两个线程优先级和时间片相同,调度器让它们轮流执行,各自输出计数值。当线程调用 rt_thread_mdelay(1000) 时让出CPU,另一个线程获得执行机会。
总结
| 要点 | 内容 |
|---|---|
| 线程组成 | 控制块 + 栈 + 入口函数 |
| 状态模型 | 初始 → 就绪 → 运行 ↔ 挂起 → 关闭 |
| 调度策略 | 优先级抢占 + 同级时间片轮转 |
| 创建方式 | rt_thread_create + rt_thread_startup |
| 延时选择 | RTOS中必须使用 rt_thread_mdelay,禁止忙等待delay |
掌握了线程管理,你就掌握了RTOS的核心。下一篇将介绍时钟与定时器管理,探索RT-Thread如何处理时间维度的任务调度。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)