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,初始计数值为 0xCountingSemaphore = xSemaphoreCreateCounting(3, 3);// 创建任务1xTaskCreate(Task1, "任务1", 10000, NULL, 1, NULL);// 创建任务2xTaskCreate(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));}}
}
结论
计数信号量是一个强大的工具,用于实现任务之间的同步和对共享资源的管理。通过适当地使用计数信号量,可以确保多任务系统的稳定性和可靠性,避免竞争条件和死锁等问题的发生。在设计多任务系统时,务必充分考虑任务的同步需求,并合理选择合适的同步机制。