这篇文章为大家介绍FreeRTOS里的 互斥锁。
文章目录
- 前言
- 一、互斥量的概念
- 二、STM32cubeMX配置互斥量
- 三、相关函数
- 1. 创建互斥量
- 2. 获取互斥量
- 3. 释放互斥量
- 四、使用互斥量访问共享资源
- 五、递归互斥锁
- 在RTOS里互斥锁是谁获取,谁就释放吗?
- 总结
前言
一、互斥量的概念
- 问 :什么是互斥量?
- 答 :互斥量其实就是互斥锁,用来保护临界(共享)资源的访问。
互斥量(Mutex)是一种同步机制,用来确保同一时刻只有一个线程或任务在访问共享资源。防止多个线程同时访问共享资源
而造成的数据不一致性,保护临界资源的访问
。
使用场景:当有多个任务 或 线程同时访问共享资源。
二、STM32cubeMX配置互斥量
关于前面的基础配置可以参考我之前的文章:STM32cubeMX配置FreeRTOS工程
创建互斥锁:
Mutex Name:互斥量名字
Allocation:分配方式
Control Block Name:互斥量控制块名字
三、相关函数
1. 创建互斥量
osMutexId_t osMutexNew(const osMutexAttr_t *attr);
返回值:
osMutexId_t :互斥量的标识符,用于后续对互斥量的操作。
参数:
attr :互斥量的属性,包括优先级、名称等。可以为 NULL ,表示使用默认属性。
2. 获取互斥量
osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout);
返回值:
osStatus_t :表示互斥量获取的状态,可能的取值包括 osOK 、 osErrorResource (资源不可
用)、 osErrorTimeout (超时)等。
参数:
mutex_id :要获取的互斥量的标识符。
timeout :等待互斥量的最大时间,通常以毫秒为单位。可以为 osWaitForever 表示无限等待,
也可以是一个具体的时间值。
3. 释放互斥量
osStatus_t osMutexRelease(osMutexId_t mutex_id);
返回值:
osStatus_t :表示互斥量释放的状态,通常为 osOK 。
参数:
mutex_id :要释放的互斥量的标识符。
四、使用互斥量访问共享资源
设置一个全局变量为共享资源,创建两个任务去访问全局变量,让变量增加。
// 共享资源-----全局变量
int share_data = 0;// 任务 2
void StartTask02(void *argument)
{/* USER CODE BEGIN StartTask02 *//* Infinite loop */for(;;){// 获取 互斥锁(上锁)osMutexAcquire(myMutex01Handle, osWaitForever);share_data++;printf("task2 share_data : %d\r\n", share_data);// 释放互斥锁(解锁)osMutexRelease(myMutex01Handle);osDelay(1000);}/* USER CODE END StartTask02 */
}// 任务 3
void StartTask03(void *argument)
{/* USER CODE BEGIN StartTask03 *//* Infinite loop */for(;;){// 获取 互斥锁(上锁)osMutexAcquire(myMutex01Handle, osWaitForever);share_data++;printf("task3 share_data : %d\r\n", share_data);// 释放互斥锁(解锁)osMutexRelease(myMutex01Handle); osDelay(1000);}/* USER CODE END StartTask03 */
}
五、递归互斥锁
在RTOS里互斥锁是谁获取,谁就释放吗?
回答 : 否。
互斥锁 / 互斥量的概念确实是 谁获取,谁就释放。但是在 FreeRTOS 里并不支持这个观点。
在 FreeRTOS 中,标准互斥锁可以由其他任务来释放。递归互斥锁实现了 谁上锁,就由谁解锁。
在 下面的例子中,创建了一个递归互斥锁
。 任务 1 获取互斥量后会延迟一段时间,在这段时间内任务2 不会释放 任务1 的互斥量。
// 创建递归互斥锁
static SemaphoreHandle_t mutex1_handle;
mutex1_handle = xSemaphoreCreateRecursiveMutex();// 任务1
void Task1Function(void * param)
{while (1){// 获取互斥量xSemaphoreTakeRecursive(mutex1_handle, portMAX_DELAY);printf("Task1 Take \r\n");printf("%s\r\n",(char*)param);vTaskDelay(5);// 释放互斥量xSemaphoreGiveRecursive(mutex1_handle);printf("Task1 Give \r\n");}
}// 任务2
void Task2Function(void * param)
{while (1){ if (xSemaphoreTakeRecursive(mutex1_handle, 0) != pdTRUE){if(xSemaphoreGiveRecursive(mutex1_handle)) printf("Task2 : xSemaphoreGive success\r\n");}else{printf("%s\r\n",(char*)param);xSemaphoreGiveRecursive(mutex1_handle); // 释放互斥量} }
}
总结
下一篇文章为大家介绍 信号量 和 队列。