二进制信号量(Semaphore)
二进制信号量和互斥锁所用的底层函数相同,xSemaphoreTake()和 xSemaphoreGive()。但不相似。
互斥锁中这两个函数分别扮演着开锁和关锁的角色。
而在二进制信号量中,却类似于 flag 的用法。具体如下:
使用流程
目的:Task2 等待 Task1 的信号并且执行任务
- 定义一个二进制信号量
- Task1:给出(Give)信号
- Task2:等待信号(Take)的到来,此时任务阻塞。
如果用 Flag 标志位类比:
bool Flag = 0
- Task1:
Flag = 1
- Task2:
if(Flag == 1)Flag=0
特殊情况
任务1 每 15 秒释放一次信号量;
任务 2 执行完毕到等待获取信号量需要 16 秒
结果:
任务 2 在完成后,可能需要等待下一个信号量的释放(即 14 秒后)才能再次执行任务。即使有多个信号量被释放,任务 2 也只会在它主动调用 xSemaphoreTake() 时获取到信号量并执行。
代码示例
在代码中,使用了 vTaskDelay来模拟变量的处理花费的时间,而不是作为阻塞作用
因为互斥锁本身是有阻塞作用的
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
SemaphoreHandle_t xBinarySemaphore;
void vTask1(void *pvParameters) {
while(1) {
vTaskDelay(15 / portTICK_PERIOD_MS);
xSemaphoreGive(xBinarySemaphore);
}
}
void vTask2(void *pvParameters) {
while(1) {
if(xSemaphoreTake(xBinarySemaphore, portMAX_DELAY)) {
vTaskDelay(16 / portTICK_PERIOD_MS);
}
}
}
void app_main() {
xBinarySemaphore = xSemaphoreCreateBinary();
xTaskCreate(vTask1, "Task1", 2048, NULL, 2, NULL);
xTaskCreate(vTask2, "Task2", 2048, NULL, 2, NULL);
}
License:
CC BY 4.0