FreeRTOS使用计数信号量进行任务同步与资源管理
介绍
在多任务系统中,任务之间的同步和对共享资源的管理是非常重要的。FreeRTOS 提供了丰富的同步机制,其中计数信号量是一种强大的工具,用于实现任务之间的同步和对资源的访问控制。
什么是计数信号量?
计数信号量是一种特殊的信号量,与二进制信号量不同,它的计数值可以超过1。计数信号量的计数值用于跟踪资源的可用性,允许多个任务同时访问共享资源,但受到最大计数值的限制。
计数信号量的创建
在 FreeRTOS 中,我们可以使用 xSemaphoreCreateCounting()
函数创建计数信号量。该函数需要两个参数:允许的最大计数值和初始计数值。
SemaphoreHandle_t xSemaphore = xSemaphoreCreateCounting(maxCount, initialCount);
计数信号量的操作
- xSemaphoreGive():释放一个计数信号量,并增加其计数值。
- xSemaphoreTake():获取一个计数信号量,如果计数为 0,则等待直到信号量变为可用。
- vSemaphoreDelete():删除一个计数信号量及其相关资源。
示例:任务同步与资源管理
让我们通过一个示例来说明计数信号量的使用。假设我们有两个任务需要访问一个共享资源,但是同时只能有三个任务访问该资源。我们可以使用计数信号量来控制对该资源的访问。
#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
// 定义计数信号量句柄
SemaphoreHandle_t xCountingSemaphore;
// 定义共享资源
int sharedResource = 0;
// 任务函数
void Task1(void *pvParameters);
void Task2(void *pvParameters);
void setup() {
Serial.begin(115200);
// 创建计数信号量,允许的最大计数值为 3,初始计数值为 0
xCountingSemaphore = xSemaphoreCreateCounting(3, 3);
// 创建任务1
xTaskCreate(Task1, "任务1", 10000, NULL, 1, NULL);
// 创建任务2
xTaskCreate(Task2, "任务2", 10000, NULL, 1, NULL);
}
void loop() {
vTaskDelete(NULL);
}
// 任务1函数
void Task1(void *pvParameters) {
while (1) {
// 获取计数信号量
if (xSemaphoreTake(xCountingSemaphore, portMAX_DELAY) == pdTRUE) {
// 访问共享资源
sharedResource++;
Serial.print("任务1: 共享资源增加至 ");
Serial.println(sharedResource);
// 释放计数信号量
xSemaphoreGive(xCountingSemaphore);
// 等待一段时间
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
}
// 任务2函数
void Task2(void *pvParameters) {
while (1) {
// 获取计数信号量
if (xSemaphoreTake(xCountingSemaphore, portMAX_DELAY) == pdTRUE) {
// 访问共享资源
sharedResource--;
Serial.print("任务2: 共享资源减少至 ");
Serial.println(sharedResource);
// 释放计数信号量
xSemaphoreGive(xCountingSemaphore);
// 等待一段时间
vTaskDelay(pdMS_TO_TICKS(1500));
}
}
}
结论
计数信号量是一个强大的工具,用于实现任务之间的同步和对共享资源的管理。通过适当地使用计数信号量,可以确保多任务系统的稳定性和可靠性,避免竞争条件和死锁等问题的发生。在设计多任务系统时,务必充分考虑任务的同步需求,并合理选择合适的同步机制。