一、为什么需要互斥信号量
前面的学习中:
调度锁、临界段不可避免的破坏了实时性,还有二值信号量存在这样的隐患——“优先级翻转”
优先级翻转
简单来说,就是由于信号量被低优先级任务占用,即使遇到高优先级任务,它也得阻塞,实时性得不到保证
二、概念及原理
2.1定义
一种特殊的二值信号量,具有防止优先级翻转的特性,可临时提高低优先级任务(让其释放信号量),让任务独占资源,也因为这样特殊的优先级继承机制,它只能在任务中起作用
FreeRTOS中的互斥信号量包含两种:mutex、recursivemutex,后者可以解决mutex可能出现的死锁问题
2.2工作原理
2.2.1优先级继承
核心关键:低优先级任务临时提高优先级,有机会释放信号量,从而高优先级得以获取
2.2.2解决死锁
死锁是由于占用锁的任务在未释放前,继续占用锁,相当于把自己锁住
递归互斥信号量支持拥有该信号量使用权的任务重复多次获取,而不会死锁。 任务成功获取几次递归互斥信号量,就要返还几次,在此之前,递归互斥信号量都处于无效状态。
三、互斥信号量API
3.1创建互斥信号量
#include "FreeRTOS.h"
#include "semphr.h"
/*创建互斥信号量*/
SemaphoreHandle_t xSemaphoreCreatMutex(void)
return: NULL 堆空间不足
any other value 信号量句柄
matters need attention:
互斥信号量只能在任务中使用
configUSE_MUTEXES必须置1
3.2获取占用互斥信号量的任务句柄
#include "FreeRTOS.h"
#include "semphr.h"
/*获取当前占用mutex的任务句柄*/
//用于占用mutex之前的判断操作
TaskHandle_t xSemaphoreGetMutexHolder(SemaphoreHandle_t xMutex)
params: 互斥信号量句柄
return: NULL 信号量不是互斥信号量 或 互斥信号量当前未被占用
any other value 任务句柄
matters need attention:
INCLUDE_xSemaphoreGetMutexHolder必须置1
四、递归互斥信号量API
4.1创建递归互斥信号量
#include "FreeRTOS.h"
#include "semphr.h"
/*创建递归互斥信号量*/
SemaphoreHandle_t xSemaphoreCreatRecursiveMutex(void)
return: NULL 堆空间不足
any other value 信号量句柄
matters need attention:
互斥信号量只能在任务中使用
configUSE_RECURSIVE_MUTEXES必须置1
4.2获取递归互斥信号量
#include "FreeRTOS.h"
#include "semphr.h"
/*获取递归互斥信号量 不同于其他信号量的获取!!! 这是递归互斥信号量专用!!!*/
BaseType_t xSemaphoreTakeRecursiveMutex(SemaphoreHandle_t xMutex,TickType_t xTicksToWait)
params: xMutex 递归互斥信号量句柄
xTicksToWait 阻塞等待时间
return: pdPASS 获取成功
pdFAIL 阻塞超时
matters need attention:
互斥信号量只能在任务中使用
不能在临界段内调用
4.3释放递归互斥信号量
#include "FreeRTOS.h"
#include "semphr.h"
/*释放递归互斥信号量 不同于其他信号量的释放!!! 这是递归互斥信号量专用!!!*/
BaseType_t xSemaphoreGiveRecursiveMutex(SemaphoreHandle_t xMutex)
params: xMutex 递归互斥信号量句柄
return: pdPASS 获取成功
pdFAIL 此信号量持有者不是当前任务
matters need attention:
互斥信号量只能在任务中使用
不能在临界段内调用
无论是mutex还是recursivemutex 注意成对使用!!!