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

一文带你深度了解FreeRTOS——计数型信号量

 

本文记录FreeRTOS的计数型信号量知识,希望我的分享对你有所帮助!

目录

一、计数型信号量简介 

二、创建计数型信号量

1、动态创建计数型信号量

2、静态创建计数型信号量

三、结语 


一、计数型信号量简介 

计数型信号量在FreeRTOS中用于管理对共享资源的访问。它允许多任务间同步和互斥,通过设置最大计数值来限制资源的使用。任务可以“获取”信号量,如果计数值大于0,则计数减1并继续执行;如果计数为0,任务会被阻塞直到信号量被释放。信号量被“释放”时,计数值增加,可能会唤醒阻塞的任务。这个机制帮助管理并发任务对有限资源的访问。

我们知道,二值信号量相当于长度为1的队列,那么计数型信号量就是长度大于1的队列,作为用户不需要知道队列里存的是什么,只需要关心队列是否为空就行。

计数型信号量通常被应用于以下场合:

【1】用于事件计数

在事件每次发生的时候,就在事件处理函数中释放信号量,即增加信号量的计数值,其他任务会在此时获取信号量,即信号量计数值减一(此处的信号量值就是结构体成员变量:uxMessagesWaiting),进而根据信号量计数值的变化来处理事件。

在这种场合中创建的计数型信号量初始计数值为0.

【2】资源管理

这时的信号量值表示的是当前资源的可用数量。比如会场剩余的座位数量。一个任务如果想获得资源的使用权,首先必须获取信号量,获取成功后的信号量值就会减一。当信号量的值为0的时候就说明以已经没有资源了。而且,如果一个任务使用完资源后,就一定要释放信号量,释放信号量以后信号量的值就会加一。

在这种场合中信号量的初始值就应该是资源的数量,比如会场的座位数量为100,那么创建信号量的时候信号量的初始值就应该是100.

二、创建计数型信号量

1、动态创建计数型信号量

xSemaphoreCreateCounting 是 FreeRTOS 中用于创建计数型信号量的函数。计数型信号量可以用于任务之间的同步和互斥。

SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount);

参数

  • uxMaxCount:

    • 类型: UBaseType_t
    • 描述: 计数型信号量可以持有的最大计数值。即信号量的“最大值”。
  • uxInitialCount:

    • 类型: UBaseType_t
    • 描述: 创建信号量时的初始计数值。即信号量的“初始值”。这个值应该小于或等于 uxMaxCount

返回值

  • 成功: 返回一个 SemaphoreHandle_t 类型的信号量句柄。这个句柄用于以后对信号量的操作。
  • 失败: 返回 NULL,表示信号量创建失败。创建失败可能是由于内存不足或其他原因。

创建实例:

#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"// 定义信号量句柄
SemaphoreHandle_t xSemaphore;void vTask1(void *pvParameters) {for (;;) {// 请求信号量if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {// 成功获取信号量,执行任务// ...// 释放信号量xSemaphoreGive(xSemaphore);}// 延时,模拟任务执行vTaskDelay(pdMS_TO_TICKS(1000));}
}void vTask2(void *pvParameters) {for (;;) {// 请求信号量if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {// 成功获取信号量,执行任务// ...// 释放信号量xSemaphoreGive(xSemaphore);}// 延时,模拟任务执行vTaskDelay(pdMS_TO_TICKS(500));}
}int main(void) {// 创建计数型信号量,最大计数为3,初始计数为3xSemaphore = xSemaphoreCreateCounting(3, 3);if (xSemaphore == NULL) {// 信号量创建失败,进行错误处理// ...}// 创建两个任务xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);xTaskCreate(vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL);// 启动调度器vTaskStartScheduler();// 启动调度器后不会返回for (;;);
}

2、静态创建计数型信号量

xSemaphoreCreateCountingStatic() 是 FreeRTOS 提供的一个 API,用于创建一个静态分配的计数型信号量。它的主要功能是用于管理对共享资源的访问。

函数原型:

SemaphoreHandle_t xSemaphoreCreateCountingStatic(UBaseType_t uxMaxCount,UBaseType_t uxInitialCount,StaticSemaphore_t *pxSemaphoreBuffer
);

参数说明:

  • uxMaxCount:信号量的最大计数值,即可以支持的最大资源数量。
  • uxInitialCount:信号量的初始计数值,通常是资源的初始可用数量。
  • pxSemaphoreBuffer:指向 StaticSemaphore_t 结构体的指针,这个结构体用于保存信号量的静态分配数据。

返回值:

  • 如果成功创建信号量,返回信号量句柄(SemaphoreHandle_t)。
  • 如果创建失败,返回 NULL

使用示例:

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"// 定义信号量缓冲区
StaticSemaphore_t xSemaphoreBuffer;
SemaphoreHandle_t xCountingSemaphore;// 任务函数
void vTask1(void *pvParameters) {for (;;) {if (xSemaphoreTake(xCountingSemaphore, portMAX_DELAY) == pdTRUE) {// 访问共享资源// 执行任务代码printf("Task 1 acquired the semaphore.\n");// 释放共享资源xSemaphoreGive(xCountingSemaphore);}vTaskDelay(pdMS_TO_TICKS(1000)); // 延时1秒}
}void vTask2(void *pvParameters) {for (;;) {if (xSemaphoreTake(xCountingSemaphore, portMAX_DELAY) == pdTRUE) {// 访问共享资源// 执行任务代码printf("Task 2 acquired the semaphore.\n");// 释放共享资源xSemaphoreGive(xCountingSemaphore);}vTaskDelay(pdMS_TO_TICKS(1000)); // 延时1秒}
}int main(void) {// 创建计数型信号量xCountingSemaphore = xSemaphoreCreateCountingStatic(3,              // 最大计数值3,              // 初始计数值&xSemaphoreBuffer  // 静态分配的缓冲区);if (xCountingSemaphore == NULL) {// 处理信号量创建失败的情况printf("Failed to create semaphore.\n");return 1;}// 创建任务xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);xTaskCreate(vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL);// 启动调度器vTaskStartScheduler();// 如果到达此处,说明调度器启动失败for (;;);return 0;
}

说明:

  • xSemaphoreCreateCountingStatic() 被用于创建一个最大计数值为 3 的计数型信号量,初始计数值也为 3。
  • vTask1 和 vTask2 是两个任务,它们会尝试获取和释放信号量,模拟对共享资源的访问。
  • xSemaphoreTake() 和 xSemaphoreGive() 分别用于获取和释放信号量。
  • vTaskDelay() 用于任务间的延时,以模拟任务的执行时间和避免过于频繁的信号量操作。

三、结语 

关于FreeRTOS的计数型信号量就分享到此了,敬请关注,一起加油!

持续更新中~~~

 


http://www.mrgr.cn/news/19017.html

相关文章:

  • 【系统架构设计师-2021年】综合知识-答案及详解
  • Anaconda安装教程就看这里
  • 首批国自然博士项目获批名单
  • 亿图图示下载安装教程EdrawMax Pro 13版超详细图文教程
  • Maven持续集成(Continuous integration,简称CI)版本友好管理
  • 9.3C++
  • 【深入了解常用类】
  • Java笔试面试题AI答之正则表达式(2)
  • 【iOS】暑期学习总结
  • Spring 学习笔记
  • 探索 Nuxt Devtools:功能全面指南
  • Vue3 中的响应式系统:深入理解 Proxy API
  • LeetCode LCR088.使用最小花费爬楼梯
  • wget下载速度受到哪些因素影响?
  • 揭秘Java后端框架:从Spring到Netty,全方位解析!
  • 【归并分而治之】逆序对的应对之策
  • KTH5641 系列具有模拟输出的比例式线性霍尔效应传感器
  • 【Qt】消息对话框 QMessageBox
  • 7.Lab Six —— Cow Fork
  • 6. MyBatis中的@Mapper注解和XML映射文件的区别是什么?