FreeRTOS中创建任务的顺序是否会影响任务运行的顺序?【面试重点】

结论

任务的运行顺序 和 创建顺序 没有任何关系! FreeRTOS 是抢占式调度器,任务执行顺序只由 2 个规则决定:

  1. 优先级高的任务 → 永远先运行(核心规则)
  2. 同优先级任务新创建的任务会立即抢占当前任务 ,直接导致后创建、先运行

原理(FreeRTOS 调度核心机制)

1. 抢占式调度器(最重要)

FreeRTOS 默认开启 抢占式调度

  • 只要有更高优先级 的任务进入就绪态,CPU 会立刻停止当前任务,去运行高优先级任务
  • 优先级:数值越大,优先级越高(CMSIS-V2 / STM32CubeMX 配置)

2. 同优先级任务的规则

创建的任务优先级完全相同 (都是 osPriorityNormal):

  1. 同优先级任务默认使用 时间片轮转调度
  2. 新创建的任务 会被插入到就绪链表的头部
  3. 调度器会立即切换 到这个新任务运行→ 表现为:谁后创建,谁先抢 CPU 运行

3. 补充:调度器启动前创建任务

如果在 vTaskStartScheduler() 之前创建所有任务:

  • 所有任务排队进入就绪链表
  • 调度器启动后,运行最高优先级任务
  • 同优先级:运行链表第一个任务(先创建的先运行)

运行机制

cpp 复制代码
// 都是 osPriorityNormal 同优先级
xTaskCreate(Input_Task, ...);  // 先创建
xTaskCreate(platform_task, ...); // 后创建

执行流程:

  1. CPU 正在运行 game1_task
  2. 调用 xTaskCreate 创建 platform_task
  3. 新任务优先级 = 当前任务优先级
  4. FreeRTOS 直接抢占切换 :暂停 game1_task,先运行 platform_task
  5. 所以你看到:后创建的任务先运行

可复制验证代码(直观看到效果)

cpp 复制代码
// 三个同优先级任务
void Task1(void *p)
{
    while(1)
    {
        LCD_PrintString(0,0,"Task1 Run");
        vTaskDelay(500);
    }
}

void Task2(void *p)
{
    while(1)
    {
        LCD_PrintString(0,2,"Task2 Run"); // 后创建,会先打印!
        vTaskDelay(500);
    }
}

void game1_task(void *params)
{
    // 先创建 Task1
    xTaskCreate(Task1, "Task1", 128, NULL, osPriorityNormal, NULL);
    // 后创建 Task2
    xTaskCreate(Task2, "Task2", 128, NULL, osPriorityNormal, NULL);

    while(1)
    {
        vTaskDelay(100);
    }
}

✅ 现象:LCD 先显示 Task2 Run,验证后创建先运行


避坑提醒(STM32F103 + FreeRTOS 专属)

  1. 绝对不要依赖「任务创建顺序」控制执行流程 同优先级任务的执行顺序是不确定的,换芯片 / 升级库可能失效

  2. 需要优先运行的任务 → 提高优先级例:平台控制任务需要优先运行

    复制代码
    // 高优先级
    xTaskCreate(platform_task, ..., osPriorityAboveNormal, NULL);
    // 普通优先级
    xTaskCreate(Input_Task, ..., osPriorityNormal, NULL);
  3. 业务同步不要靠执行顺序队列、任务通知、互斥锁、信号量 做任务同步(你项目中已用队列,正确)

  4. 抢占式调度默认开启这是 FreeRTOS 标准配置,不要关闭,否则系统实时性崩溃

相关推荐
人邮异步社区3 小时前
怎么把C语言学到精通?
c语言·开发语言
xiaobobo33308 小时前
C语言中宏定义宏名和宏值之间的关系
c语言·宏定义·语义型
a44931536212 小时前
MacBook USB-C不充电故障诊断:从PD握手到主板供电链路
c语言·开发语言·macos·电脑
a44931536213 小时前
iPhone 充电故障的全链路诊断——从 Lightning/USB-C 接口到 Tristar 充电 IC
c语言·macos·ios·电脑·硬件架构·iphone
qq_4480111613 小时前
C语言中的getchar()
c语言·开发语言
天空'之城13 小时前
C 语言工业级通用组件手写 15:累加和校验
c语言·嵌入式开发·工业级组件·累加和校验
碎光拾影1 天前
i.MX6ULL时钟系统配置指南
c语言·arm开发·嵌入式硬件
GeekArch1 天前
第28讲:避坑——AI堆栈分配错误、栈溢出BUG
c语言·人工智能·stm32·mcu·学习·bug
wuyk5551 天前
59.嵌入式C语言高级宏定义实战:多行宏、字符串化与符号拼接
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网·51单片机
无相求码1 天前
C程序的内存到底怎么分的?栈、堆、全局区一张图讲清楚
c语言