当前位置:   article > 正文

FreeRTOS_互斥量_学习笔记

FreeRTOS_互斥量_学习笔记

互斥量

数值只有0或1
谁获得互斥量,就必须由谁释放同一个互斥量。在这里插入图片描述
但其实在freeRTOS中,任务A获取的互斥锁,任务B也能释放。因此谁上锁谁开锁只是约定,在程序实现上不是强制的。
可重入的函数"是指:多个任务同时调用它、任务和中断同时调用它,函数的运行也是安全的。可重入的函数也被称为"线程安全”(thread safe)。
每个任务都维持自己的栈、自己的CPU寄存器,如果一个函数只使用局部变量,那么它就是线程安全的。
函数中一旦使用了全局变量、静态变量、其他外设,它就不是"可重入的",如果该函数正在被调用,就必须阻止其他任务、中断再次调用它。
上述问题的解决方法是:任务A访问这些全局变量、函数代码时,独占它,就是上个锁。这些全局变量、函数代码必须被独占地使用,它们被称为临界资源。
互斥量的使用过程如下:

互斥量初始值为1
任务A想访问临界资源,先获得并占有互斥量,然后开始访问
任务B也想访问临界资源,也要先获得互斥量:被别人占有了,于是阻塞
任务A使用完毕,释放互斥量;任务B被唤醒、得到并占有互斥量,然后开始访问临界资源
任务B使用完毕,释放互斥量
  • 1
  • 2
  • 3
  • 4
  • 5

互斥量函数

使用互斥量需要定义:

#define configUSE_MUTEXES 1
  • 1

创建

成功则返回句柄,失败则返回NULL

SemaphoreHandle_t xSemaphoreCreateMutex( void ); // 动态分配
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );

  • 1
  • 2
  • 3

获取与释放

不能在中断中使用。除此之外与信号量相同

void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );//删除
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );//释放
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);//获取

  • 1
  • 2
  • 3
  • 4

优先级反转问题

使用信号量时,有时会出现低优先级先运行,高优先级不运行的问题,原因在于:
低优先级的任务先创建,先获取了信号量;
不需要取信号量的中优先级任务第二个创建,阻塞了低优先级任务,此时低优先级任务信号量还没释放;
高优先级任务后创建,此时take信号量,被阻塞,无法运行
FreeRTOS_信号量_学习笔记中,修改三个任务的优先级:

    xTaskCreate(CarTask, "car1", 128, &g_cars[0], osPriorityNormal, NULL);
    xTaskCreate(Car2Task, "car2", 128, &g_cars[1], osPriorityNormal+1, NULL);
    xTaskCreate(Car3Task, "car3", 128, &g_cars[2], osPriorityNormal+2, NULL);	
  • 1
  • 2
  • 3

同时将第二辆车的任务中获取信号量和释放信号量的语句删除。此时CarTask被Car2Task阻塞,Car3Task无法运行
此时,只要将信号量替换为互斥量即可解决优先级反转问题。其原理是用了优先级继承功能。
假设持有互斥锁的是任务A,如果更高优先级的任务B也尝试获得这个锁
任务B说:你既然持有宝剑,又不给我,那就继承我的愿望吧
于是任务A就继承了任务B的优先级
这就叫:优先级继承
等任务A释放互斥锁时,它就恢复为原来的优先级
互斥锁内部就实现了优先级的提升、恢复

递归锁

互锁

A获得互斥量M1
B获得互斥量M2
A还想获得M2才能运行,A阻塞
B还想获得M1才能运行,B阻塞
AB都阻塞,都无法释放其所持有的互斥量
  • 1
  • 2
  • 3
  • 4
  • 5

自锁

A获得了互斥量M
他调用了一个库函数,库函数也想获取互斥量M
库函数阻塞,A休眠,无法释放互斥量
  • 1
  • 2
  • 3

解决以上问题,可以使用递归锁,其特性为:

  1. 任务A获得递归锁M后,它还可以多次去获得这个锁
  2. "take"了N次,要"give"N次,这个锁才会被释放

递归锁的函数和一般互斥量的函数名不一样,参数类型一样。

递归锁互斥量
创建xSemaphoreCreateRecursiveMutexxSemaphoreCreateMutex
获得xSemaphoreTakeRecursivexSemaphoreTake
释放xSemaphoreGiveRecursivexSemaphoreGive

递归锁主要用于解决同一个线程多次获取同一个锁时的同步问题,不涉及多个线程之间的并发访问。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/630865
推荐阅读
相关标签
  

闽ICP备14008679号