FreeRTOS 中的 task 优先级 及 实际测试验证

官方文章在这里:https://www.freertos.org/taskandcr.html

Task 可以理解为 线程 ,线程当然就是优先级(priority)的概念,如果两个线程,有不同的优先级,当然就是优先级高的优先执行(占用CPU资源)。 那问题来了, 是怎么 占用 呢?

如果一个线程A在运行过程中,另一个优先级更高的线程B启动了(进入 Ready 状态),则B会立即执行(进入 Running 状态),A则立马会停止(进入 Ready 状态)

现在做一个测试程序来验证一下,

测试环境:ESP32-WROOM-32E/IDF v4.3

代码如下:2个线程,task2 高(priority=2) task1 低(priority = 1)


void my_delay(int val)
{
    for (int k = 0; k < 10; ++k)
    {
        int i = 0;
        for (; i < 100; ++i)
            for (int j = 0; j < 10000; ++j)
                ;

        printf("in dealy... %d\n", val);
    }
}

void task(void * pvParameters)
{
    int flag = *(int*)pvParameters;

    while (true)
    {
        int tick = XTHAL_GET_CCOUNT();
        printf("%d:task%d running...\n", tick,flag);
        my_delay(flag);

        printf("%d:task%d running...DONE.%d\n", tick, flag,XTHAL_GET_CCOUNT());

        vTaskDelay(2000 / portTICK_PERIOD_MS);//SLEEP 2秒钟
    }
}


void app_main(void)
{
    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
           CONFIG_IDF_TARGET,
           chip_info.cores,
           (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
           (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    int flag1 = 1;
    xTaskCreate(&task, "task1", 1024 * 2,&flag1 , 1, NULL);
    int flag2 = 2;
    xTaskCreate(&task, "task2", 1024 * 2,&flag2 , 2, NULL);

    vTaskDelay(100);
}

预计结果:先打印 2, 完了再打印 1,实际结果如下(交叉打印):

I (0) cpu_start: Starting scheduler on APP CPU.
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, 
17780636:task1 running...
17786772:task2 running...
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
17786772:task2 running...DONE.182456170
in dealy... 1
17780636:task1 running...DONE.149535080

分析:与预计结果不相符是因为这个模块是 2 核心的,所以可以同时运行

我们再加一个线程 task 3, priority = 3

    int flag1 = 1;
    xTaskCreate(&task, "task1", 1024 * 2,&flag1 , 1, NULL);
    int flag2 = 2;
    xTaskCreate(&task, "task2", 1024 * 2,&flag2 , 2, NULL);
    int flag3 = 3;
    xTaskCreate(&task, "task3", 1024 * 2,&flag3 , 3, NULL);

运行结果如下:

I (0) cpu_start: Starting scheduler on APP CPU.
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, 
17786580:task2 running...
50932139:task3 running...
in dealy... 2
17781121:task1 running...
in dealy... 3
in dealy... 2
in dealy... 3
in dealy... 2
in dealy... 3
in dealy... 2
in dealy... 3
in dealy... 2
in dealy... 3
in dealy... 2
in dealy... 3
in dealy... 2
in dealy... 3
in dealy... 2
in dealy... 3
in dealy... 2
in dealy... 3
in dealy... 2
17786580:task2 running...DONE.182470416
in dealy... 3
50932139:task3 running...DONE.149376526
in dealy... 1
in dealy... 1
in dealy... 1
in dealy... 1
in dealy... 1
in dealy... 1
in dealy... 1
in dealy... 1
in dealy... 1
in dealy... 1
17781121:task1 running...DONE.312668596

分析:task3,task2 分属不同核心同时运行,task1因为级别(Priority)低 所以一直等待。 当task2,task3 进入BLOCK状态时,task1 开始执行。与结果预期一致!

接下来带的一个问题,如果级别(Priority)都一样,会怎么运行呢?这里就涉及一个配置问题,请参考:https://www.freertos.org/a00110.html#configUSE_TIME_SLICING

简单的说:

    配置打开:则相同级别(priority)的线程同时运行,每个线程会被顺序分配时间片。

    配置关闭:相同级别(priority)的线程会顺序执行,先运行的线程会一直运行到结束,另一个线程再开始运行。

我们把三个线程都改成相同的priority:

    int flag1 = 1;
    xTaskCreate(&task, "task1", 1024 * 2,&flag1 , 1, NULL);
    int flag2 = 2;
    xTaskCreate(&task, "task2", 1024 * 2,&flag2 , 1, NULL);
    int flag3 = 3;
    xTaskCreate(&task, "task3", 1024 * 2,&flag3 , 1, NULL);

运行结果如下:

I (0) cpu_start: Starting scheduler on APP CPU.
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, 
17781552:task1 running...
50932563:task2 running...
50938208:task3 running...
in dealy... 3
in dealy... 2
in dealy... 1
in dealy... 3
in dealy... 2
in dealy... 1
in dealy... 3
in dealy... 2
in dealy... 1
in dealy... 3
in dealy... 2
in dealy... 1
in dealy... 3
in dealy... 2
in dealy... 1
in dealy... 3
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 3
in dealy... 1
in dealy... 3
in dealy... 2
in dealy... 1
in dealy... 3
in dealy... 2
in dealy... 1
in dealy... 3
50938208:task3 running...DONE.247676578
in dealy... 1
17781552:task1 running...DONE.248214922
in dealy... 2
50932563:task2 running...DONE.248237042

分析:结果如预期一致。也说明 ESP32的IDF4.3默认是把 TIME_SLICING 打开的

找到 FreeRTOS.h 并把里面的配置改为 0

#ifndef configUSE_TIME_SLICING
	#define configUSE_TIME_SLICING 0 //这里原来是 1
#endif

fullclean 之后重新运行。

为了效果更好,我加了第4个线程

    int flag1 = 1;
    xTaskCreate(&task, "task1", 1024 * 2,&flag1 , 1, NULL);
    int flag2 = 2;
    xTaskCreate(&task, "task2", 1024 * 2,&flag2 , 1, NULL);
    int flag3 = 3;
    xTaskCreate(&task, "task3", 1024 * 2,&flag3 , 1, NULL);
    int flag4 = 4;
    xTaskCreate(&task, "task4", 1024 * 2,&flag4 , 1, NULL);

  这次运行的时候发现一个问题,因为我们的主函数(app_main() )其实也是一个线程,会干扰我们的结果。所以我在 task() 中增加了一个 delay ,保证开始执行的时候,主线程已经结束。

void task(void * pvParameters)
{
    int flag = *(int*)pvParameters;

    vTaskDelay(150);// 增加这行,以避免主函数干扰
    while (true)
    {
        int tick = XTHAL_GET_CCOUNT();
        printf("%d:task%d running...\n", tick,flag);
        my_delay(flag);

        printf("%d:task%d running...DONE.%d\n", tick, flag,XTHAL_GET_CCOUNT());

        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}

运行结果如下:

I (0) cpu_start: Starting scheduler on APP CPU.
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, 
289989045:task2 running...
257656240:task3 running...
291588057:task1 running...
260856198:task4 running...
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
in dealy... 2
in dealy... 1
291588057:task1 running...DONE.421771277
in dealy... 4
in dealy... 3
in dealy... 4
in dealy... 3
in dealy... 4
in dealy... 3
in dealy... 4
in dealy... 3
in dealy... 4
in dealy... 3
in dealy... 4
in dealy... 3
in dealy... 4
in dealy... 3
in dealy... 4
in dealy... 3
in dealy... 4
in dealy... 3
in dealy... 4
260856198:task4 running...DONE.550369295
in dealy... 3
257656240:task3 running...DONE.517558482
in dealy... 2
289989045:task2 running...DONE.551025233

分析:先执行task 1,2,结束后再执行task 3,4 。虽然priority一样,但是顺序执行。如预期一致

--END--

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值