• FreeRTOS 互斥量 优先级反转(翻转)和优先级继承 详解


    目录

    什么是互斥量?

    什么是优先级反转(翻转)和优先级继承

    互斥量相关 API 函数

    优先级反转(翻转)示例

    使用互斥量优化优先级反转(翻转)问题示例


    什么是互斥量?

    在多数情况下,互斥型信号量和二值型信号量非常相似,但是从功能上二值型信号量用于同步, 而互斥型信号量用于资源保护。

    互斥型信号量和二值型信号量还有一个最大的区别,互斥型信号量可以有效解决优先级反转现 象。

    什么是优先级反转(翻转)和优先级继承

    以上图为例,系统中有3个不同优先级的任务H/M/L,最高优先级任务H和最低优先级任务L通过 信号量机制,共享资源。目前任务L占有资源,锁定了信号量,Task H运行后将被阻塞,直到Task L释放信号量后,Task H才能够退出阻塞状态继续运行。但是Task H在等待Task L释放信号量的过 程中,中等优先级任务M抢占了任务L,从而延迟了信号量的释放时间,导致Task H阻塞了更长时 间,这种现象称为优先级倒置或优先级反转(翻转)。

    优先级继承:

    当一个互斥信号量正在被一个低优先级的任务持有时, 如果此时有个高优先级的任 务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务 会将低优先级任务的优先级提升到与自己相同的优先级。

    优先级继承并不能完全的消除优先级翻转的问题,它只是尽可能的降低优先级翻转带来的影响。

    互斥量相关 API 函数

    互斥信号量不能用于中断服务函数中!

                                    函数                                描述
    xSemaphoreCreateMutex()使用动态方法创建互斥信号量
    xSemaphoreCreateMutexStatic()使用静态方法创建互斥信号量
    SemaphoreHandle_t xSemaphoreCreateMutex( void )

    参数:

    返回值:

    成功,返回对应互斥量的句柄;

    失败,返回 NULL 。

    优先级反转(翻转)示例

    如下图,低优先级工作后高优先级被阻塞,然后发生优先级反转,中优先级比高优先级先工作

    1.打开CubeMX,将FreeRTOS移植到STM32F103C8T6,具体看我之前写过的文章

    将FreeRTOS移植到STM32F103C8T6

    2.增加三个任务,优先级分别从高到底

    3.增加一个二值信号量,导出代码

    4.代码编写:

    freertos.c

    1. void StartTaskH(void const * argument)
    2. {
    3. for(;;)
    4. {
    5. xSemaphoreTake(myBinarySem01Handle,portMAX_DELAY);
    6. printf("高优先级获得二值信号量,开始工作\r\n");
    7. HAL_Delay(1000);
    8. printf("工作完毕后,释放二值信号量\r\n");
    9. xSemaphoreGive(myBinarySem01Handle);
    10. osDelay(1000);
    11. }
    12. }
    13. void StartTaskM(void const * argument)
    14. {
    15. for(;;)
    16. {
    17. printf("占用cpu资源,不工作\r\n");
    18. osDelay(1000);
    19. }
    20. }
    21. void StartTaskL(void const * argument)
    22. {
    23. for(;;)
    24. {
    25. xSemaphoreTake(myBinarySem01Handle,portMAX_DELAY);
    26. printf("低优先级获得二值信号量,开始工作\r\n");
    27. HAL_Delay(3000);
    28. printf("工作完毕后,释放二值信号量\r\n");
    29. xSemaphoreGive(myBinarySem01Handle);
    30. osDelay(1000);
    31. }
    32. }

    5.打开串口助手,看执行结果:低优先级工作后实现优先级反转,中等优先级比高优先级先工作

    使用互斥量优化优先级反转(翻转)问题示例

    1.使用CubeMX在优先级反转示例中增加互斥量,导出代码

    2.编写代码

    freertos.c

    1. void StartTaskH(void const * argument)
    2. {
    3. for(;;)
    4. {
    5. xSemaphoreTake(myMutex01Handle,portMAX_DELAY);
    6. printf("高优先级获得互斥量,开始工作\r\n");
    7. HAL_Delay(1000);
    8. printf("工作完毕后,释放互斥量\r\n");
    9. xSemaphoreGive(myMutex01Handle);
    10. osDelay(1000);
    11. }
    12. }
    13. void StartTaskM(void const * argument)
    14. {
    15. for(;;)
    16. {
    17. printf("占用cpu资源,不工作\r\n");
    18. osDelay(1000);
    19. }
    20. }
    21. void StartTaskL(void const * argument)
    22. {
    23. for(;;)
    24. {
    25. xSemaphoreTake(myMutex01Handle,portMAX_DELAY);
    26. printf("低优先级获得互斥量,开始工作\r\n");
    27. HAL_Delay(3000);
    28. printf("工作完毕后,释放互斥量\r\n");
    29. xSemaphoreGive(myMutex01Handle);
    30. osDelay(1000);
    31. }
    32. }

    3.打开串口助手,看执行结果:低优先级工作后高优先级工作,最后到中等优先级

  • 相关阅读:
    在CentOS操作系统上使用yum安装/使用/卸载Docker容器引擎
    机器人到达指定位置的方法数问题
    ARM 和 AMD 架构的区别
    年薪30万+的HR这样做数据分析!(附关键指标&免费模版)
    拼图小游戏
    机器学习-概述与贝叶斯算法
    基于 Flutter 和 Firebase 实现的小游戏 I/O Pinball - 谷歌 I / O 2022
    @Resource和@Autowired
    Vue.js核心技术解析与uni-app跨平台实战开发学习笔记 第7章 Vue.js高级进阶 7.8 slot插槽
    01 Sekiro服务器部署和第一个示例部署成功,js逆向和加解密
  • 原文地址:https://blog.csdn.net/m0_74712453/article/details/134001652