当前位置: 首页 > news >正文

B站Michale_ee——ESP32_IDF SDK——FreeRTOS_4信号量、互斥量

  • 信号量可以控制任务同步,即任务之间的执行按照一定顺序执行;
  • RTOS中的任务间通信、任务同步、任务互斥;
    • 任务间通信:不同任务间进行数据的交换和信息的传递,可以通过消息队列等方式;
    • 任务同步:确保任务按照特定顺序执行,可以通过信号量、事件标志组等方式;
    • 任务互斥:保证同一时刻只能有一个任务访问临界资源,防止资源同时方式访问或造成资源数据不一致;

一、二进制信号量

1.二进制信号量简介

  • 二进制信号只有0和1两个值。
    • 信号量为1时,任务可以获取信号量并执行该任务;
    • 信号量为0时,任务获取不到信号量,进入阻塞状态,暂停执行;

2.二进制信号量API简介

(1)创建二进制信号量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(2)释放信号量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)获取信号量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.示例代码及运行结果

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "freertos/semphr.h"       // add by lxlint iCount = 0;
SemaphoreHandle_t Semphr_Handle;void Task1(void *pvparam)
{while(1){xSemaphoreTake(Semphr_Handle, portMAX_DELAY);for(int i=0; i<10; i++){iCount++;printf("Task1 iCount:%d\n", iCount);vTaskDelay(pdMS_TO_TICKS(1000));}xSemaphoreGive(Semphr_Handle);vTaskDelay(pdMS_TO_TICKS(1000));}
}void Task2(void *pvparam)
{while(1){xSemaphoreTake(Semphr_Handle, portMAX_DELAY);for(int i=0; i<10; i++){iCount++;printf("Task2 iCount:%d\n", iCount);vTaskDelay(pdMS_TO_TICKS(1000));}xSemaphoreGive(Semphr_Handle);vTaskDelay(pdMS_TO_TICKS(1000));}
}void app_main(void)
{Semphr_Handle = xSemaphoreCreateBinary();xSemaphoreGive(Semphr_Handle);xTaskCreate(Task1, "Task1", 1024*5, NULL, 1, NULL);xTaskCreate(Task2, "Task2", 1024*5, NULL, 1, NULL);
}

在这里插入图片描述

二、计数型信号量

1.计数型信号量简介

  • 计数型信号量的值可大于1;
  • 计数型信号量用于对多个资源进行管理;例如:停车场中有多个停车位,用计数型信号量表示停车位的个数:有车进入,计数型信号量减1;有车开出,计数型信号量加1;

2.计数型信号量API简介

(1)获取可用信号量的个数

在这里插入图片描述
在这里插入图片描述

(2)释放信号量、获取信号量API 同 二进制信号量

(3)创建计数型信号量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.示例代码及运行结果

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "freertos/semphr.h"       // add by lxlSemaphoreHandle_t Semphr_Handle;void CarInTask(void *pvparam)
{UBaseType_t EmptySpaceCount = 0;BaseType_t iResult;while(1){EmptySpaceCount = uxSemaphoreGetCount(Semphr_Handle);printf("EmptySpaceCount:%d\n", EmptySpaceCount);iResult = xSemaphoreTake(Semphr_Handle, 0);if(iResult == pdPASS)printf("One Car in!\n");elseprintf("No Space!\n");vTaskDelay(pdMS_TO_TICKS(1000));}
}void CarOutTask(void *pvparam)
{while(1){vTaskDelay(pdMS_TO_TICKS(6000));xSemaphoreGive(Semphr_Handle);}
}void app_main(void)
{Semphr_Handle = xSemaphoreCreateCounting(5, 5);// xSemaphoreGive(Semphr_Handle);xTaskCreate(CarInTask, "CarInTask", 1024*5, NULL, 1, NULL);xTaskCreate(CarOutTask, "CarOutTask", 1024*5, NULL, 1, NULL);
}

在这里插入图片描述

三、互斥量

1.互斥量简介

  • 互斥量用于控制任务对临界资源的访问,确保一段时间内只有一个任务访问临界资源;
  • 互斥量和二值信号量十分相似,但互斥量有优先级继承机制,能避免出现优先级反转的情况;
    • 优先级继承机制:持有互斥锁的任务的优先级会在另一个更高优先级的任务尝试获取同一互斥锁时被提升。已经持有互斥锁的任务被称为“继承”了试图“夺取”同一互斥锁的任务的优先级。当互斥锁被释放时,继承的优先级将被“取消继承”(即,在持有互斥锁期间继承了更高优先级的任务将在互斥锁被释放后恢复到其原始优先级)。
      在这里插入图片描述

    • 优先级反转:

2.互斥量API简介

(1)创建互斥量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)释放信号量、获取信号量API 同 二进制信号量

3.示例代码及运行结果

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "freertos/semphr.h"       // add by lxlSemaphoreHandle_t MutexHandle = NULL;
TaskHandle_t Task1Handle = NULL;void Task1(void *pvparam)
{BaseType_t iRet;UBaseType_t Task1Priority;while(1){printf("Task1 begin\n");iRet = xSemaphoreTake(MutexHandle, 1000);if(iRet == pdPASS){printf("Task1 Take Mutex Successfully\n");for(int i=0; i<5; i++){printf("Task1 i=%d\n", i);Task1Priority = uxTaskPriorityGet(NULL);printf("Task1 Priority:%d\n", Task1Priority);vTaskDelay(pdMS_TO_TICKS(1000));}xSemaphoreGive(MutexHandle);printf("Task1 Give Mutex!\n");vTaskDelay(pdMS_TO_TICKS(5000));}else{printf("Task1 Take Mutex Fail\n");vTaskDelay(pdMS_TO_TICKS(1000));}}}void Task2(void *pvparam)
{printf("Task2 begin\n");vTaskDelay(pdMS_TO_TICKS(1000));while(1){;}
}void Task3(void *pvparam)
{BaseType_t iRet;UBaseType_t Task1Priority;printf("Task3 begin\n");vTaskDelay(pdMS_TO_TICKS(1000));while(1){iRet = xSemaphoreTake(MutexHandle, 1000);if(iRet == pdPASS){printf("Task3 Take Mutex Successfully\n");Task1Priority = uxTaskPriorityGet(Task1Handle);printf("Task1 Priority :%d\n", Task1Priority);for(int i=0; i<5; i++){printf("Task3 i=%d\n", i);vTaskDelay(pdMS_TO_TICKS(1000));}xSemaphoreGive(MutexHandle);printf("Task3 Give Mutex!\n");vTaskDelay(pdMS_TO_TICKS(5000));}else{printf("Task3 Take Mutex Fail\n");vTaskDelay(pdMS_TO_TICKS(1000));}}
}void app_main(void)
{MutexHandle = xSemaphoreCreateMutex();vTaskSuspendAll();xTaskCreatePinnedToCore(Task1, "Task1", 1024*5, NULL, 1, &Task1Handle, 1);      //! ESP32-S3为双核,CPU0主要运行WiFi和蓝牙;CPU1用于运行应用程序;xTaskCreatePinnedToCore(Task2, "Task2", 1024*5, NULL, 2, NULL, 1);xTaskCreatePinnedToCore(Task3, "Task3", 1024*5, NULL, 3, NULL, 1);xTaskResumeAll();
}

在这里插入图片描述

四、递归互斥量

1.递归互斥锁的使用场景

  • 任务1在使用资源A的同时,之后又需要使用资源B
    • 如果用互斥量,需要创建2个互斥量,在使用资源时上锁,不需要使用资源时,解锁
    • 用递归互斥量只需要创建1个,在使用1次资源时,上1次锁,不需要使用资源时,解1次锁;
      在这里插入图片描述

2.递归互斥量的API简介

(1)创建递归互斥量

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(2)获取递归互斥量

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

(3)释放递归互斥量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.示例代码及运行结果

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "freertos/semphr.h"       // add by lxlSemaphoreHandle_t RecursiveMutexHandle = NULL;
TaskHandle_t Task1Handle = NULL;void Task1(void *pvparam)
{while(1){// printf("--------------------------\n");printf("Task1 begin\n");xSemaphoreTakeRecursive(RecursiveMutexHandle, portMAX_DELAY);printf("Task1 Take A!\n");for(int i=0; i<5; i++){printf("Task1 i:%d for A\n", i);vTaskDelay(pdMS_TO_TICKS(1000));}xSemaphoreTakeRecursive(RecursiveMutexHandle, portMAX_DELAY);printf("Task1 Take B!\n");for(int i=0; i<5; i++){printf("Task1 i:%d for B\n", i);vTaskDelay(pdMS_TO_TICKS(1000));}printf("Task1 Give B!\n");xSemaphoreGiveRecursive(RecursiveMutexHandle);vTaskDelay(pdMS_TO_TICKS(3000));printf("Task1 Give A!\n");xSemaphoreGiveRecursive(RecursiveMutexHandle);vTaskDelay(pdMS_TO_TICKS(3000));}
}void Task2(void *pvparam)
{vTaskDelay(pdMS_TO_TICKS(1000));while(1){// printf("--------------------------\n");printf("Task2 begin\n");xSemaphoreTakeRecursive(RecursiveMutexHandle, portMAX_DELAY);printf("Task2 Take A!\n");for(int i=0; i<5; i++){printf("Task2 i:%d for A\n", i);vTaskDelay(pdMS_TO_TICKS(1000));}printf("Task2 Give A!\n");xSemaphoreGiveRecursive(RecursiveMutexHandle);vTaskDelay(pdMS_TO_TICKS(3000));}
}void app_main(void)
{RecursiveMutexHandle = xSemaphoreCreateRecursiveMutex();vTaskSuspendAll();xTaskCreatePinnedToCore(Task1, "Task1", 1024*5, NULL, 1, &Task1Handle, 1);      //! ESP32-S3为双核,CPU0主要运行WiFi和蓝牙;CPU1用于运行应用程序;xTaskCreatePinnedToCore(Task2, "Task2", 1024*5, NULL, 1, NULL, 1);xTaskResumeAll();
}

在这里插入图片描述

相关文章:

  • 情境领导理论——AI与思维模型【89】
  • c/c++开发调试工具之gdb
  • AI 驱动的智能交通系统:从拥堵到流畅的未来出行
  • Allegro23.1新功能之如何使用文件预览功能操作指导
  • FormCalc 支持的编程语言和软件
  • 流水线相关计算【计算机组成与体系结构】
  • 数字智慧方案5873丨智慧交通设计方案(57页PPT)(文末有下载方式)
  • Linux_sudo命令的使用与机制
  • 力扣刷题 -- 206.反转链表
  • 第Y3周:yolov5s.yaml文件解读
  • TCP三次握手和四次挥手(简要版)
  • 多模态大模型轻量化探索-视觉大模型SAM(Segment Anything Model)
  • Linux 下使用tcpdump进行网络分析原
  • SpringTask
  • 自动化测试项目2 --- 比特纵横 [软件测试实战 Java 篇]
  • Baklib知识中台驱动企业服务智能升级
  • 深入理解C++构造函数:从入门到实践
  • win10系统安卓开发环境搭建
  • Spring 分批处理 + 冷热数据分离:历史订单高效迁移与数据清理实战
  • 数字智慧方案6206丨智慧园区大数据整体解决方案(45页PPT)(文末有下载方式)
  • 研究完蚂蚁搬家,我好像明白了为什么我们总是堵车
  • 五一假期多地政府食堂对外开放:部分机关食堂饭菜“秒没”
  • 取消了“仅退款”,商家就可以高枕无忧了吗?
  • 投资者建议发行优惠套票给“被套”小股东,张家界:将研究考虑
  • 学有质量、查有力度、改有成效,广大党员干部落实中央八项规定精神
  • 亮剑浦江丨上海网信部门处罚一批医疗服务类互联网企业,三大类问题值得关注