【deepseek】多任务调度详解
·
RT-Thread 多任务调度详解
📊 调度器架构
RT-Thread 采用基于优先级的抢占式调度,支持时间片轮转:
1. 任务状态
// 任务状态定义
RT_THREAD_INIT // 初始状态
RT_THREAD_READY // 就绪状态
RT_THREAD_RUNNING // 运行状态
RT_THREAD_SUSPEND // 挂起状态
RT_THREAD_CLOSE // 关闭状态
2. 优先级管理
- 优先级范围:0-255(0最高,255最低)
- 系统优先级:0-31(系统线程)
- 用户优先级:32-255(用户线程)
- 相同优先级:支持时间片轮转调度
🔄 调度策略
抢占式调度
// 高优先级任务抢占低优先级任务
void high_priority_task(void* param)
{
while(1) {
rt_kprintf("High priority task running\n");
rt_thread_mdelay(1000);
}
}
void low_priority_task(void* param)
{
while(1) {
rt_kprintf("Low priority task running\n");
rt_thread_mdelay(1000);
}
}
// 创建任务(优先级不同)
rt_thread_create("high", high_priority_task, NULL, 512, 10, 10);
rt_thread_create("low", low_priority_task, NULL, 512, 20, 10);
时间片轮转
// 相同优先级任务使用时间片
static void task1_entry(void* parameter)
{
while(1) {
rt_kprintf("Task1 running\n");
rt_thread_delay(5); // 主动让出CPU
}
}
static void task2_entry(void* parameter)
{
while(1) {
rt_kprintf("Task2 running\n");
rt_thread_delay(5);
}
}
// 创建相同优先级任务,设置时间片
rt_thread_t task1 = rt_thread_create("task1", task1_entry, NULL,
512, 10, 10); // 优先级10,时间片10 ticks
rt_thread_t task2 = rt_thread_create("task2", task2_entry, NULL,
512, 10, 10); // 优先级10,时间片10 ticks
⚙️ 调度相关API
任务控制
// 创建线程
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);
// 启动线程
rt_err_t rt_thread_startup(rt_thread_t thread);
// 删除线程
rt_err_t rt_thread_delete(rt_thread_t thread);
// 挂起线程
rt_err_t rt_thread_suspend(rt_thread_t thread);
// 恢复线程
rt_err_t rt_thread_resume(rt_thread_t thread);
// 让出CPU
rt_err_t rt_thread_yield(void);
延时函数
// 系统延时(基于系统节拍)
rt_err_t rt_thread_delay(rt_tick_t tick); // 相对延时
rt_err_t rt_thread_sleep(rt_tick_t tick); // 同delay
rt_err_t rt_thread_mdelay(rt_int32_t ms); // 毫秒延时
// 绝对时间延时
rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick);
📈 调度器工作流程
调度触发时机
-
主动触发
rt_thread_yield(); // 主动让出CPU rt_thread_delay(); // 延时等待 rt_thread_suspend(); // 挂起自己 -
被动触发
- 中断处理完成时
- 任务状态改变时
- 时间片用完时
- 优先级改变时
调度器源码简析
// 调度器核心(简化版)
void rt_schedule(void)
{
// 1. 查找最高优先级就绪任务
struct rt_thread *to_thread;
to_thread = _get_highest_priority_thread();
// 2. 检查是否需要切换
if (to_thread != rt_current_thread) {
// 3. 执行上下文切换
rt_hw_context_switch((rt_uint32_t)&rt_current_thread->sp,
(rt_uint32_t)&to_thread->sp);
}
}
🎯 调度示例
示例1:优先级演示
#include <rtthread.h>
static rt_thread_t tid1, tid2, tid3;
static void thread1_entry(void *parameter)
{
rt_uint32_t count = 0;
while (1) {
rt_kprintf("thread1 count: %d\n", count++);
rt_thread_mdelay(500); // 延时500ms
}
}
static void thread2_entry(void *parameter)
{
rt_uint32_t count = 0;
while (1) {
rt_kprintf("thread2 count: %d\n", count++);
rt_thread_mdelay(1000); // 延时1s
}
}
static void thread3_entry(void *parameter)
{
rt_uint32_t count = 0;
while (1) {
rt_kprintf("thread3 count: %d\n", count++);
rt_thread_mdelay(2000); // 延时2s
}
}
int scheduler_demo(void)
{
// 创建三个不同优先级的线程
tid1 = rt_thread_create("thread1", thread1_entry, RT_NULL,
1024, 6, 10);
tid2 = rt_thread_create("thread2", thread2_entry, RT_NULL,
1024, 7, 10);
tid3 = rt_thread_create("thread3", thread3_entry, RT_NULL,
1024, 8, 10);
// 启动线程
if (tid1 != RT_NULL) rt_thread_startup(tid1);
if (tid2 != RT_NULL) rt_thread_startup(tid2);
if (tid3 != RT_NULL) rt_thread_startup(tid3);
return 0;
}
示例2:时间片轮转
#include <rtthread.h>
#define THREAD_STACK_SIZE 512
#define THREAD_PRIORITY 10
#define THREAD_TIMESLICE 5 // 5个tick的时间片
static void thread_entry(void* parameter)
{
rt_uint32_t value;
rt_uint32_t count = 0;
value = (rt_uint32_t)parameter;
while (1) {
rt_kprintf("thread %d is running, count = %d\n", value, count++);
// 长时间运行,测试时间片切换
for (int i = 0; i < 1000000; i++);
}
}
int timeslice_demo(void)
{
rt_thread_t tid;
// 创建两个相同优先级的线程
tid = rt_thread_create("thread1",
thread_entry,
(void*)1,
THREAD_STACK_SIZE,
THREAD_PRIORITY,
THREAD_TIMESLICE);
if (tid != RT_NULL)
rt_thread_startup(tid);
tid = rt_thread_create("thread2",
thread_entry,
(void*)2,
THREAD_STACK_SIZE,
THREAD_PRIORITY,
THREAD_TIMESLICE);
if (tid != RT_NULL)
rt_thread_startup(tid);
return 0;
}
🔍 调度调试技巧
1. 使用 Finsh 命令
# 查看线程状态
list_thread
# 输出示例
thread pri status sp stack size max used left tick error
-------- --- ------- ---------- ---------- ------ ---------- ---
thread1 10 running 0x00000060 0x00000200 28% 0x0000000a 000
thread2 10 ready 0x00000060 0x00000200 30% 0x0000000a 000
tshell 20 ready 0x00000080 0x00001000 15% 0x0000000a 000
2. 调度器钩子函数
// 注册调度器钩子
void my_scheduler_hook(struct rt_thread* from, struct rt_thread* to)
{
rt_kprintf("switch from [%s] to [%s]\n", from->name, to->name);
}
// 安装钩子
rt_scheduler_sethook(my_scheduler_hook);
⚠️ 注意事项
-
优先级反转问题
- 使用互斥锁的优先级继承机制
- 避免高优先级任务等待低优先级任务
-
堆栈大小设置
- 根据函数调用深度合理设置
- 使用
list_thread检查堆栈使用率
-
中断处理
- 中断中不能使用可能导致阻塞的API
- 快速处理,将耗时操作放到线程中
-
死锁预防
- 按固定顺序获取多个锁
- 设置超时机制
📊 性能优化建议
-
减少上下文切换
- 合理设置时间片大小
- 避免频繁创建/删除线程
-
优先级设置策略
- I/O密集型任务:较低优先级
- 计算密集型任务:较高优先级
- 实时任务:最高优先级
-
使用静态线程
// 静态线程创建(无动态内存分配) static struct rt_thread thread; static rt_uint8_t thread_stack[512]; rt_thread_init(&thread, "static", thread_entry, RT_NULL, &thread_stack[0], sizeof(thread_stack), 10, 10);
需要我详细讲解调度算法实现、优先级反转解决方案或具体应用场景吗?
更多推荐



所有评论(0)