FreeRTOS 互斥信号量
一、FreeRTOS互斥信号量的基本概念
FreeRTOS中的互斥信号量是一种特殊的二进制信号量,用于实现任务间的互斥访问。它主要用于保护临界区代码,防止多个任务同时访问共享资源而导致的数据不一致问题。互斥信号量的工作机制基于“请求-授予”模型,即当一个任务需要访问共享资源时,会先请求互斥信号量,如果信号量可用(即当前没有任务持有信号量),则任务获得信号量并进入临界区;如果信号量不可用(即已有任务持有信号量),则任务会被阻塞,直到信号量被释放。
二、FreeRTOS互斥信号量的使用步骤
包含头文件:
在使用FreeRTOS互斥信号量之前,需要包含相应的头文件。通常,我们需要包含FreeRTOS.h
和task.h
头文件,以使用FreeRTOS提供的API函数。
定义互斥信号量:
使用xSemaphoreCreateMutex
函数来创建一个互斥信号量。这个函数会返回一个信号量句柄,用于后续的信号量操作。
加锁与解锁:
在访问共享资源之前,任务需要使用xSemaphoreTake
函数来获取互斥信号量(即加锁)。如果信号量不可用,任务会被阻塞,直到信号量被释放。完成共享资源的访问后,任务需要使用xSemaphoreGive
函数来释放信号量(即解锁)。
销毁互斥信号量:
当不再需要使用互斥信号量时,可以使用vSemaphoreDelete
函数来销毁它。注意,在销毁信号量之前,应确保没有任务持有该信号量。
xSemaphoreHandle xMutex = xSemaphoreCreateMutex();
// 加锁
if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
// 访问共享资源
// ...
// 解锁
xSemaphoreGive(xMutex);
}
vSemaphoreDelete(xMutex);
三、FreeRTOS互斥信号量实例分析
以下是一个简单的FreeRTOS互斥信号量使用实例,展示了如何在两个任务之间保护共享资源的访问。
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
// 共享资源
int sharedResource = 0;
// 互斥信号量句柄
xSemaphoreHandle xMutex;
// 任务1:增加共享资源值
void vTask1(void *pvParameters) {
for (int i = 0; i < 10; i++) {
// 加锁
if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
// 访问共享资源
sharedResource++;
printf("Task1: sharedResource = %d\n", sharedResource);
// 解锁
xSemaphoreGive(xMutex);
// 模拟任务处理时间
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
}
// 任务2:减少共享资源值
void vTask2(void *pvParameters) {
for (int i = 0; i < 10; i++) {
// 加锁
if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
// 访问共享资源
sharedResource--;
printf("Task2: sharedResource = %d\n", sharedResource);
// 解锁
xSemaphoreGive(xMutex);
// 模拟任务处理时间
vTaskDelay(150 / portTICK_PERIOD_MS);
}
}
}
int main(void) {
// 创建互斥信号量
xMutex = xSemaphoreCreateMutex();
// 创建任务1和任务2
xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
xTaskCreate(vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL);
// 启动调度器
vTaskStartScheduler();
// 永远不会到达这里,因为调度器已经启动
for (;;);
}
在这个实例中,我们创建了两个任务vTask1
和vTask2
,它们分别负责增加和减少共享资源sharedResource
的值。为了确保对共享资源的独占访问,我们使用了互斥信号量xMutex
。在访问共享资源之前,任务会先请求互斥信号量(加锁),完成访问后释放信号量(解锁)。这样,即使两个任务同时运行,也不会出现数据竞争问题。