- #include "gd32f4xx.h"
- #include "systick.h"
- #include <stdio.h>
- #include "main.h"
- #include "FreeRTOS.h"
- #include "task.h"
- #include "semphr.h"
- #include "Usart0.h"
-
- TaskHandle_t task_handler;
- TaskHandle_t task_key_handler;
- TaskHandle_t task1_handler;
- TaskHandle_t task2_handler;
- SemaphoreHandle_t sema_handler;
-
- void task1(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task1\n");
- } else {
- printf("task1 Error\n");
- }
- }
- }
-
- void task2(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task2\n");
- } else {
- printf("task2 Error\n");
- }
- }
- }
-
- void task_key(void *pvParameters) {
- FlagStatus pre_state = RESET;
- BaseType_t result;
- while(1) {
- FlagStatus state = gpio_input_bit_get(GPIOA, GPIO_PIN_0);
- if(SET == state && pre_state == RESET) {
- // 当前高电平, 上一次为低电平,按下
- pre_state = state;
-
- result = xSemaphoreGive(sema_handler);
- } else if(RESET == state && pre_state == SET) {
- // 当前高电平, 上一次为低电平,抬起
- pre_state = state;
- }
- vTaskDelay(20);
- }
- }
-
- void start_task(void *pvParameters) {
- taskENTER_CRITICAL();
-
- xTaskCreate(task_key, "task_key", 64, NULL, 2, &task_key_handler);
- xTaskCreate(task1, "task1", 64, NULL, 3, &task1_handler);
- xTaskCreate(task2, "task2", 64, NULL, 2, &task2_handler);
- vTaskDelete(task_handler);
-
- taskEXIT_CRITICAL();
- }
-
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- }
-
- static void GPIO_config() {
- // 时钟初始化
- rcu_periph_clock_enable(RCU_GPIOA);
- // 配置GPIO模式
- gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0);
- }
-
- int main(void)
- {
- NVIC_SetPriorityGrouping(NVIC_PRIGROUP_PRE4_SUB0);
- systick_config();
- GPIO_config();
- Usart0_init();
-
- sema_handler = xSemaphoreCreateBinary();
- xTaskCreate(start_task, "start_task", 128, NULL, 1, &task_handler);
- vTaskStartScheduler();
-
- while(1) {}
- }
观察,两个任务是否获得信号。
改变两个任务的优先级,观察两个任务信号的获取情况。
案例二在案例1的基础上,通过串口接收,来发送信号。
串口发送信号
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- xSemaphoreGiveFromISR(sema_handler, NULL);
- }
xSemaphoreGiveFromISR中断中发送信号
计数型信号量
功能 | 描述 |
xSemaphoreCreateCounting | 创建计数型信号量 |
xSemaphoreTake | 等待信号 |
xSemaphoreGive | 发送信号 |
信号量的创建
- SemaphoreHandle_t xSemaphoreCreateCounting( const UBaseType_t uxMaxCount,
- const UBaseType_t uxInitialCount);
参数说明:
- const UBaseType_t uxMaxCount最大计数值。
- const UBaseType_t uxInitialCount初始化当前计数值。
返回值为信号量的句柄。
等待信号操作
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xBlockTime );
1、SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
2、TickType_t xBlockTime表示要等待的时间。通常我们一直等到有信号到来,这里我们可以填写portMAX_DELAY
3、返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
发送信号操作
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
- SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
- 返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
案例一- 开启两个任务,等待信号,接收到信号后,处理耗时操作
- 开启按键扫描,点击按键时发送信号
main.c
- #include "gd32f4xx.h"
- #include "systick.h"
- #include <stdio.h>
- #include "main.h"
- #include "FreeRTOS.h"
- #include "task.h"
- #include "semphr.h"
- #include "Usart0.h"
-
- TaskHandle_t task_handler;
- TaskHandle_t task_key_handler;
- TaskHandle_t task1_handler;
- TaskHandle_t task2_handler;
- SemaphoreHandle_t sema_handler;
-
- void task1(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task1 %ld\n", uxSemaphoreGetCount(sema_handler));
- } else {
- printf("task1 Error\n");
- }
- vTaskDelay(2500);
- }
- }
-
- void task2(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task2 %ld\n", uxSemaphoreGetCount(sema_handler));
- } else {
- printf("task2 Error\n");
- }
- vTaskDelay(2500);
- }
- }
-
- void task_key(void *pvParameters) {
- FlagStatus pre_state = RESET;
- BaseType_t result;
- while(1) {
- FlagStatus state = gpio_input_bit_get(GPIOA, GPIO_PIN_0);
- if(SET == state && pre_state == RESET) {
- // 当前高电平, 上一次为低电平,按下
- pre_state = state;
-
- result = xSemaphoreGive(sema_handler);
- // if(result == pdTRUE) {
- // printf("semaphore give success\n");
- // } else {
- // printf("semaphore give error\n");
- // }
- } else if(RESET == state && pre_state == SET) {
- // 当前高电平, 上一次为低电平,抬起
- pre_state = state;
- }
- vTaskDelay(20);
- }
- }
-
- void start_task(void *pvParameters) {
- taskENTER_CRITICAL();
-
- xTaskCreate(task_key, "task_key", 64, NULL, 2, &task_key_handler);
- xTaskCreate(task1, "task1", 64, NULL, 3, &task1_handler);
- xTaskCreate(task2, "task2", 64, NULL, 2, &task2_handler);
- vTaskDelete(task_handler);
-
- taskEXIT_CRITICAL();
- }
-
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- }
-
- static void GPIO_config() {
- // 时钟初始化
- rcu_periph_clock_enable(RCU_GPIOA);
- // 配置GPIO模式
- gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0);
- }
-
- int main(void)
- {
- NVIC_SetPriorityGrouping(NVIC_PRIGROUP_PRE4_SUB0);
- systick_config();
- GPIO_config();
- Usart0_init();
-
- sema_handler = xSemaphoreCreateCounting(100, 0);
- xTaskCreate(start_task, "start_task", 128, NULL, 1, &task_handler);
- vTaskStartScheduler();
-
- while(1) {}
- }
观察,两个任务是否获得信号。
频繁点击按键,观察效果。
案例二在案例一的基础上,通过串口接收,来发送信号。
串口发送信号
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- xSemaphoreGiveFromISR(sema_handler, NULL);
- }
xSemaphoreGiveFromISR中断中发送信号
互斥信号量 功能 | 描述 |
xSemaphoreCreateMutex | 创建互斥信号量 |
xSemaphoreTake | 等待信号 |
xSemaphoreGive | 发送信号 |
信号量的创建
互斥信号量创建语法
SemaphoreHandle_t xSemaphoreCreateMutex();
返回值为信号量的句柄。
等待信号操作
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xBlockTime );
1、SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
2、TickType_t xBlockTime表示要等待的时间。通常我们一直等到有信号到来,这里我们可以填写portMAX_DELAY
3、返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
发送信号操作
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
- SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
- 返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
案例一- 开启两个任务,分别去等待信号。
- 开启按键扫描任务,当点击按键时,发送信号
main.c
- #include "gd32f4xx.h"
- #include "systick.h"
- #include <stdio.h>
- #include "main.h"
- #include "FreeRTOS.h"
- #include "task.h"
- #include "semphr.h"
- #include "Usart0.h"
-
- TaskHandle_t task_handler;
- TaskHandle_t task_key_handler;
- TaskHandle_t task1_handler;
- TaskHandle_t task2_handler;
- SemaphoreHandle_t sema_handler;
-
- void task1(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task1\n");
- } else {
- printf("task1 Error\n");
- }
- }
- }
-
- void task2(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task2\n");
- } else {
- printf("task2 Error\n");
- }
- }
- }
-
- void task_key(void *pvParameters) {
- FlagStatus pre_state = RESET;
- BaseType_t result;
- while(1) {
- FlagStatus state = gpio_input_bit_get(GPIOA, GPIO_PIN_0);
- if(SET == state && pre_state == RESET) {
- // 当前高电平, 上一次为低电平,按下
- pre_state = state;
-
- result = xSemaphoreGive(sema_handler);
- } else if(RESET == state && pre_state == SET) {
- // 当前高电平, 上一次为低电平,抬起
- pre_state = state;
- }
- vTaskDelay(20);
- }
- }
-
- void start_task(void *pvParameters) {
- taskENTER_CRITICAL();
-
- xTaskCreate(task_key, "task_key", 64, NULL, 2, &task_key_handler);
- xTaskCreate(task1, "task1", 64, NULL, 3, &task1_handler);
- xTaskCreate(task2, "task2", 64, NULL, 2, &task2_handler);
- vTaskDelete(task_handler);
-
- taskEXIT_CRITICAL();
- }
-
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- }
-
- static void GPIO_config() {
- // 时钟初始化
- rcu_periph_clock_enable(RCU_GPIOA);
- // 配置GPIO模式
- gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0);
- }
-
- int main(void)
- {
- NVIC_SetPriorityGrouping(NVIC_PRIGROUP_PRE4_SUB0);
- systick_config();
- GPIO_config();
- Usart0_init();
-
- sema_handler = xSemaphoreCreateBinary();
- xTaskCreate(start_task, "start_task", 128, NULL, 1, &task_handler);
- vTaskStartScheduler();
-
- while(1) {}
- }
观察,两个任务是否获得信号。
改变两个任务的优先级,观察两个任务信号的获取情况。
案例二在案例一的基础上,通过串口接收,来发送信号。
串口发送信号
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- xSemaphoreGiveFromISR(sema_handler, NULL);
- }
xSemaphoreGiveFromISR中断中发送信号
计数型信号量 功能 | 描述 |
xSemaphoreCreateCounting | 创建计数型信号量 |
xSemaphoreTake | 等待信号 |
xSemaphoreGive | 发送信号 |
信号量的创建
- SemaphoreHandle_t xSemaphoreCreateCounting( const UBaseType_t uxMaxCount,
- const UBaseType_t uxInitialCount);
参数说明:
- const UBaseType_t uxMaxCount最大计数值。
- const UBaseType_t uxInitialCount初始化当前计数值。
返回值为信号量的句柄。
等待信号操作
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xBlockTime );
1、SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
2、TickType_t xBlockTime表示要等待的时间。通常我们一直等到有信号到来,这里我们可以填写portMAX_DELAY
3、返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
发送信号操作
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
- SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
- 返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
案例一- 开启两个任务,等待信号,接收到信号后,处理耗时操作
- 开启按键扫描,点击按键时发送信号
main.c
- #include "gd32f4xx.h"
- #include "systick.h"
- #include <stdio.h>
- #include "main.h"
- #include "FreeRTOS.h"
- #include "task.h"
- #include "semphr.h"
- #include "Usart0.h"
-
- TaskHandle_t task_handler;
- TaskHandle_t task_key_handler;
- TaskHandle_t task1_handler;
- TaskHandle_t task2_handler;
- SemaphoreHandle_t sema_handler;
-
- void task1(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task1 %ld\n", uxSemaphoreGetCount(sema_handler));
- } else {
- printf("task1 Error\n");
- }
- vTaskDelay(2500);
- }
- }
-
- void task2(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task2 %ld\n", uxSemaphoreGetCount(sema_handler));
- } else {
- printf("task2 Error\n");
- }
- vTaskDelay(2500);
- }
- }
-
- void task_key(void *pvParameters) {
- FlagStatus pre_state = RESET;
- BaseType_t result;
- while(1) {
- FlagStatus state = gpio_input_bit_get(GPIOA, GPIO_PIN_0);
- if(SET == state && pre_state == RESET) {
- // 当前高电平, 上一次为低电平,按下
- pre_state = state;
-
- result = xSemaphoreGive(sema_handler);
- // if(result == pdTRUE) {
- // printf("semaphore give success\n");
- // } else {
- // printf("semaphore give error\n");
- // }
- } else if(RESET == state && pre_state == SET) {
- // 当前高电平, 上一次为低电平,抬起
- pre_state = state;
- }
- vTaskDelay(20);
- }
- }
-
- void start_task(void *pvParameters) {
- taskENTER_CRITICAL();
-
- xTaskCreate(task_key, "task_key", 64, NULL, 2, &task_key_handler);
- xTaskCreate(task1, "task1", 64, NULL, 3, &task1_handler);
- xTaskCreate(task2, "task2", 64, NULL, 2, &task2_handler);
- vTaskDelete(task_handler);
-
- taskEXIT_CRITICAL();
- }
-
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- }
-
- static void GPIO_config() {
- // 时钟初始化
- rcu_periph_clock_enable(RCU_GPIOA);
- // 配置GPIO模式
- gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0);
- }
-
- int main(void)
- {
- NVIC_SetPriorityGrouping(NVIC_PRIGROUP_PRE4_SUB0);
- systick_config();
- GPIO_config();
- Usart0_init();
-
- sema_handler = xSemaphoreCreateCounting(100, 0);
- xTaskCreate(start_task, "start_task", 128, NULL, 1, &task_handler);
- vTaskStartScheduler();
-
- while(1) {}
- }
观察,两个任务是否获得信号。
频繁点击按键,观察效果。
案例二在案例一的基础上,通过串口接收,来发送信号。
串口发送信号
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- xSemaphoreGiveFromISR(sema_handler, NULL);
- }
xSemaphoreGiveFromISR中断中发送信号
互斥信号量 功能 | 描述 |
xSemaphoreCreateMutex | 创建互斥信号量 |
xSemaphoreTake | 等待信号 |
xSemaphoreGive | 发送信号 |
信号量的创建
互斥信号量创建语法
SemaphoreHandle_t xSemaphoreCreateMutex();
返回值为信号量的句柄。
等待信号操作
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xBlockTime );
1、SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
2、TickType_t xBlockTime表示要等待的时间。通常我们一直等到有信号到来,这里我们可以填写portMAX_DELAY
3、返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
发送信号操作
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
- SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
- 返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
案例一开启两个任务,同时等待和发送信号,观察任务调用
main.c
- #include "gd32f4xx.h"
- #include "systick.h"
- #include <stdio.h>
- #include "main.h"
- #include "FreeRTOS.h"
- #include "task.h"
- #include "semphr.h"
- #include "Usart0.h"
-
- TaskHandle_t task_handler;
- TaskHandle_t task1_handler;
- TaskHandle_t task2_handler;
- SemaphoreHandle_t sema_handler;
-
- void task1(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task1\n");
- } else {
- printf("task1 Error\n");
- }
- xSemaphoreGive(sema_handler);
- vTaskDelay(2000);
- }
- }
-
- void task2(void *pvParameters) {
- BaseType_t result;
- while(1) {
- result = xSemaphoreTake(sema_handler, portMAX_DELAY);
- if(result == pdTRUE) {
- printf("task2\n");
- } else {
- printf("task2 Error\n");
- }
- xSemaphoreGive(sema_handler);
- vTaskDelay(2000);
- }
- }
-
- void start_task(void *pvParameters) {
- taskENTER_CRITICAL();
-
- xTaskCreate(task1, "task1", 64, NULL, 2, &task1_handler);
- xTaskCreate(task2, "task2", 64, NULL, 2, &task2_handler);
- vTaskDelete(task_handler);
-
- taskEXIT_CRITICAL();
- }
-
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- }
-
-
- int main(void)
- {
- NVIC_SetPriorityGrouping(NVIC_PRIGROUP_PRE4_SUB0);
- systick_config();
- Usart0_init();
-
- sema_handler = xSemaphoreCreateMutex();
- xTaskCreate(start_task, "start_task", 128, NULL, 1, &task_handler);
- vTaskStartScheduler();
-
- while(1) {}
- }
递归互斥信号量 功能 | 描述 |
xSemaphoreCreateRecursiveMutex | 创建递归互斥信号量 |
xSemaphoreTakeRecursive | 等待信号 |
xSemaphoreGiveRecursive | 发送信号 |
信号量的创建
互斥信号量创建语法
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex();
返回值为信号量的句柄。
等待信号操作
BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xSemaphore, TickType_t xBlockTime );
1、SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
2、TickType_t xBlockTime表示要等待的时间。通常我们一直等到有信号到来,这里我们可以填写portMAX_DELAY
3、返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
发送信号操作
BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xSemaphore);
- SemaphoreHandle_t xSemaphore表示要等待的哪个信号量句柄。
- 返回值类型为BaseType_t,表示成功或者失败,取值为pdPASS和pdFAIL
示例代码:
main.c
- #include "gd32f4xx.h"
- #include "systick.h"
- #include <stdio.h>
- #include "main.h"
- #include "FreeRTOS.h"
- #include "task.h"
- #include "semphr.h"
- #include "Usart0.h"
-
- TaskHandle_t task_Handler;
- TaskHandle_t task1_Handler;
- TaskHandle_t task2_Handler;
- SemaphoreHandle_t sema_handler;
-
- void task1(void *pvParameters) {
- BaseType_t result;
- while(1) {
- printf("task1 take 0\n");
- xSemaphoreTakeRecursive(sema_handler, portMAX_DELAY);
-
- printf("task1 take 1\n");
- xSemaphoreTakeRecursive(sema_handler, portMAX_DELAY);
-
- printf("task1 give\n");
- xSemaphoreGiveRecursive(sema_handler);
- vTaskDelay(1000);
- }
- }
-
- void task2(void *pvParameters) {
- BaseType_t result;
- while(1) {
- printf("task2 take 0\n");
- xSemaphoreTakeRecursive(sema_handler, portMAX_DELAY);
-
- printf("task2 take 1\n");
- xSemaphoreTakeRecursive(sema_handler, portMAX_DELAY);
-
- printf("task2 give\n");
- xSemaphoreGiveRecursive(sema_handler);
-
- vTaskDelay(1000);
- }
- }
-
- void start_task(void *pvParameters) {
- taskENTER_CRITICAL();
-
- xTaskCreate(task1, "task1", 128, NULL, 2, &task1_Handler);
- xTaskCreate(task2, "task2", 128, NULL, 2, &task2_Handler);
- vTaskDelete(task_Handler);
-
- taskEXIT_CRITICAL();
- }
-
- void Usart0_recv(uint8_t *data, uint32_t len)
- {
- printf("recv: %s\n", data);
- }
-
- static void GPIO_config() {
- // 时钟初始化
- rcu_periph_clock_enable(RCU_GPIOA);
- // 配置GPIO模式
- gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0);
- }
-
- int main(void)
- {
- systick_config();
- GPIO_config();
- Usart0_init();
-
- sema_handler = xSemaphoreCreateRecursiveMutex();
- if(sema_handler == NULL) {
- printf("create error\r\n");
- }
- xTaskCreate(start_task, "start_task", 128, NULL, 1, &task_Handler);
- vTaskStartScheduler();
-
- while(1) {}
- }
比较
四种信号量类型的常见应用场景的比较:
1. 二进制信号量:
应用场景:二进制信号量适用于任务间的互斥、同步和事件通知。例如,当多个任务需要共享一个资源时,可以使用二进制信号量来保证同一时间只有一个任务访问该资源。
示例应用:多个任务竞争访问共享打印机资源。
2. 计数信号量:
应用场景:计数信号量适用于任务间的资源共享和限制、任务同步和事件通知。它可以表示一组可用资源的数量,任务可以通过获取计数信号量来申请和释放这些资源。
示例应用:限制同时执行的任务数量、任务间的生产者-消费者模式。
3. 互斥信号量:
应用场景:互斥信号量用于互斥访问共享资源的场景。它确保在任意给定时间只有一个任务可以访问共享资源,避免了数据竞争和不一致性。
示例应用:多个任务竞争访问共享数据结构、临界区保护。
4. 递归互斥信号量:
应用场景:递归互斥信号量适用于同一任务需要多次获取互斥资源的场景。它允许同一任务在获取资源后再次获取,而不会引起死锁。
示例应用:任务递归调用、嵌套临界区保护。
需要根据具体的应用需求选择合适的信号量类型。如果需要简单的互斥访问,互斥信号量可能是最合适的选择。如果需要限制资源数量或任务同步,计数信号量可以派上用场。而对于同一任务需要多次获取资源的情况,递归互斥信号量提供了便利。