【Freertos基础入门】深入浅出信号量

news2024/12/30 1:01:15

文章目录

  • 前言
  • 一、Freertos的信号量是什么?
  • 二、二进制信号量和计数型信号量是什么?
  • 三、信号量初步了解
    • 1.二进制信号量的使用
    • 2.give和take是什么?
    • 3.为什么需要动态和静态创建的方式?
  • 四、二进制信号量示例代码
  • 总结


前言

本系列基于stm32系列单片机来使用freerots

FreeRTOS是一个流行的实时操作系统,提供了许多功能强大的特性,其中包括信号量。信号量是一种在并发编程中常用的同步机制,用于实现资源的共享和互斥访问。本文将介绍FreeRTOS中的信号量,包括其基本概念、用法和示例。


一、Freertos的信号量是什么?

当我们在编写多任务并发程序时,经常会遇到需要多个任务共享资源的情况,比如共享一个打印机、共享一个数据缓冲区等。在这种情况下,为了保证数据的正确性和避免冲突,我们需要一种机制来控制任务对资源的访问。FreeRTOS提供了信号量来解决这个问题。

可以将信号量看作是一种特殊的计数器。它用来记录资源的可用数量。当某个任务想要使用资源时,它需要先获取(acquire)信号量。如果信号量的计数器大于0,那么该任务就可以继续执行,并且计数器会递减。这样其他任务在同一时间就无法获取相同的资源。当任务使用完资源后,它需要释放(release)信号量,这时计数器会递增,其他任务就有机会获取资源了。

实际上,信号量可以用于两种情况:互斥访问和任务同步。在互斥访问中,信号量起到了一种锁的作用,确保同一时间只有一个任务能够访问共享资源,这样可以保证数据的一致性。而在任务同步中,信号量可以用来控制多个任务的执行顺序,一个任务在等待某个事件发生时,可以等待一个信号量,当其他任务触发了这个事件并释放了信号量,等待的任务就能继续执行了。

在FreeRTOS中,我们可以使用一些函数来创建和操作信号量。通过合理地使用信号量,我们可以确保多个任务能够安全地共享资源,并且按照设计的顺序进行执行,从而提高系统的并发性能。

二、二进制信号量和计数型信号量是什么?

当我们使用FreeRTOS的信号量时,有两种常见的类型:二进制信号量和计数型信号量。

二进制信号量(Binary Semaphore):
二进制信号量就像一把开关,只有两个状态:开和关。它的计数器只能是0或1。当一个任务获取二进制信号量时,如果它是开的(计数器为1),那么它可以继续执行;如果它是关的(计数器为0),那么获取操作会被阻塞,直到有其他任务释放了信号量让它变为开。这种信号量常用于实现互斥访问,确保同一时间只有一个任务可以访问共享资源。

计数型信号量(Counting Semaphore):
计数型信号量的计数器不仅仅只是0和1,它可以是任意非负整数。当一个任务获取计数型信号量时,如果计数器大于0,那么计数器会减1,并且获取操作会立即返回;如果计数器为0,那么获取操作会被阻塞,直到有其他任务释放了信号量让计数器变为非零。这种信号量常用于表示资源的可用数量,比如空闲的内存块或可用的任务槽位。

区别:

二进制信号量只有两个状态(开和关),而计数型信号量的计数器可以是任意非负整数。
二进制信号量常用于互斥访问,确保同一时间只有一个任务可以访问共享资源。计数型信号量通常用于表示可用资源的数量。
二进制信号量的计数器只能通过获取和释放操作切换状态。计数型信号量的计数器可以通过获取和释放操作增加或减少。
二进制信号量只能实现互斥访问,而计数型信号量不仅可以实现互斥访问,还可以用于任务同步、事件触发等应用场景。
要根据具体的需求选择信号量的类型,以及合适的获取和释放操作,以确保任务间的资源共享和同步能够正常进行。

三、信号量初步了解

1.二进制信号量的使用

  1. 动态创建函数xSemaphoreCreateBinary()
    函数原型如下:
/* 创建一个二进制信号量,返回它的句柄。
* 此函数内部会分配信号量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateBinary( void );
  1. 静态创建函数xSemaphoreCreateBinaryStatic()
    函数原型如下:
/* 创建一个二进制信号量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个StaticSemaphore_t结构体,并传入它的指针
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t
*pxSemaphoreBuffer );
  1. 二进制信号量的删除函数
    对于动态创建的信号量,不再需要它们时,可以删除它们以回收内存。
    vSemaphoreDelete可以用来删除二进制信号量、计数型信号量,函数原型如下:
/*
* xSemaphore: 信号量句柄,你要删除哪个信号量
*/
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
  1. give/take函数
    在任务中使用:
    1.xSemaphoreGive
    函数原型如下:
/*参数为要give的信号量,
返回值:pdTRUE表示成功,
如果二进制信号量的计数值已经是1,再次调用此函数则返回失败;
如果计数型信号量的计数值已经是最大值,再次调用此函数则返回失败*/
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );

2.xSemaphoreTake
函数原型如下:

/*参数为要take的信号量,等待的时间
返回值:pdTRUE表示成功
*/
BaseType_t xSemaphoreTake(
SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait
);

在中断中使用:
1.xSemaphoreGiveFromISR

函数原型如下:

/*参数为要give的信号量,如果释放信号量导致更高优先级的任务变为了就绪态,
则*pxHigherPriorityTaskWoken = pdTRUE*/
/*返回值:pdTRUE表示成功,
如果二进制信号量的计数值已经是1,再次调用此函数则返回失
败;
如果计数型信号量的计数值已经是最大值,再次调用此函数则返
回失败*/
BaseType_t xSemaphoreGiveFromISR(
SemaphoreHandle_t xSemaphore,
BaseType_t *pxHigherPriorityTaskWoken
);

2.xSemaphoreTakeFromISR

函数原型如下:

/*xSemaphore 信号量句柄,获取哪个信号量
pxHigherPriorityTaskWoken
如果获取信号量导致更高优先级的任务变为了就绪态,
则*pxHigherPriorityTaskWoken = pdTRUE
返回值 pdTRUE表示成功
*/
BaseType_t xSemaphoreTakeFromISR(
SemaphoreHandle_t xSemaphore,
BaseType_t *pxHigherPriorityTaskWoken
);

2.give和take是什么?

在这里插入图片描述
通过上图可以看到任务1先take,然后二进制信号量变成1,当任务2需要take时,发现二进制信号量是1,则任务等待任务1give后,二进制信号量变成0后任务2才take到信号量,然后信号量又变成1,从此往复。

3.为什么需要动态和静态创建的方式?

在前面的博客我们看到了很多函数,在queue中,他有动态创建和静态创建,那freertos的编写代码的人难道没事找事吗?肯定不然,
下面就是freertos代码编写者为什么需要这样做的原因:
FreeRTOS提供了两种方式来创建任务、队列、信号量等内核对象:动态创建和静态创建。

动态创建:

动态创建是在运行时动态分配内存来创建内核对象。通过调用API函数,FreeRTOS会在堆上为内核对象动态分配内存空间。
动态创建灵活,可以根据具体的需求动态调整内核对象的数量和大小。
动态创建可以在运行时创建和删除内核对象,可以根据系统的动态需求进行动态管理。
动态创建适用于需要动态管理内存的场景,比如对象的数量和大小在运行时发生变化,或者内存资源受限的情况。
静态创建:

静态创建是在编译时静态分配内存来创建内核对象。用户需要提前为内核对象预留内存空间,并在创建时使用静态分配的内存空间。
静态创建可以避免在运行时进行内存分配和释放的开销,节省了系统的运行时间和资源消耗。
静态创建需要提前估计和分配内存空间,并在编译时固定了内核对象的数量和大小。
静态创建适用于内存资源相对稳定,内核对象数量和大小较为确定的场景,可以提高系统的可靠性和性能。
动态创建和静态创建各有其适用场景。动态创建适合需要在运行时动态管理内核对象的情况,而静态创建适合内存资源相对稳定,对象数量和大小可以在编译时确定的情况。选择合适的创建方式可以根据系统的需求、资源约束和代码设计来做出权衡。

四、二进制信号量示例代码


uint32_t count = 0;
SemaphoreHandle_t s;

void Task(void *p)
{
	
	while(1)
	{
		xSemaphoreTake(s,pdMS_TO_TICKS(1000));//信号量1
		
		printf("Count:%d\r\n",count);
		
		xSemaphoreGive(s);//信号量变成0
		
		vTaskDelay(pdMS_TO_TICKS(500));
	}
	
	vTaskDelete(NULL);
	vvSemaphoreDelete(s);//在任务的外面删除,如果删除了,可能是出错了!!!
}

void Task2(void *p)
{
	while(1)
	{
		xSemaphoreTake(s,pdMS_TO_TICKS(1000));//信号量1
		
		count++;
		
		xSemaphoreGive(s);//信号量变成0
		
		vTaskDelay(1);
	}
	
	vTaskDelete(NULL);
}

void TaskTest(void)
{
	s = xSemaphoreCreateBinary( );
	
	xTaskCreate(Task,"MyTask",50,&count,1,NULL);
	xTaskCreate(Task2,"MyTask2",50,&count,3,NULL);
	
	vTaskStartScheduler();
}

在这里插入图片描述
注意:如果没有信号量,可以就会冲突

总结

信号量是FreeRTOS中用于实现资源的共享和互斥访问的重要机制。本文介绍了信号量的基本概念、创建和初始化、获取和释放操作以及用途。通过合理地使用信号量,可以提高系统并发性能,并确保共享资源的正确访问。在实际应用中,根据具体需求选择适当的信号量类型和操作方式,可以更好地利用FreeRTOS的功能来设计健壮的并发应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/910482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker之镜像与数据卷

镜像 简介 1.镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于环境开发的软件,他包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量、配置文件 2.将所有的应用和环境11,直接打包成docker镜像&…

健康检测智能睡眠床垫方案

《2022中国睡眠质量调查报告》调查结果显示,16%的被调查者存在夜间睡眠时间不足6个小时,表现为24点以后才上床睡觉,并且在6点之前起床;有83.81%的被调查者经常受到睡眠问题困扰,其中入睡困难占2…

文心一言 VS 讯飞星火 VS chatgpt (79)-- 算法导论7.4 4题

四、请用go语言,证明:RANDOMIZED-QUICKSORT 期望运行时间是 Ω(nlgn)。 文心一言: 首先,为了证明RANDOMIZED-QUICKSORT的期望运行时间是Ω(nlg n),我们需要证明在最坏的情况下,该算法的运行时间是O(nlg n)。然后&…

无涯教程-PHP.INI File Configuration函数

PHP配置文件php.ini是影响PHP功能的最终且最直接的方法。每次初始化PHP时都会读取php.ini文件。换句话说,无论是模块版本的httpd重新启动还是CGI版本的每次脚本执行都重新启动。如果未显示您的更改,请记住停止并重新启动httpd。 该配置文件已注释完整。键区分大小写,关键字值不…

阿里云服务器-修改ecs操作系统,把window系统更换成Linux操作系统

其他sql格式也在更新中,可直接查看这个系列,要是没有你需要的格式,可在评论或私信我 总目录 目录-后期更新打算 hive的nvl中的子查询 总目录我这个是window,默认应该都是window,我需要改成Linux系统第一步&#xff…

浅谈搭建CobaltStrike云服务器可能会遇到的一些问题

1.文件上传 若要将本机的文件上传至云服务器,你需通过Xshell来实现 先在xshell连接云服务器,命令行中执行rz命令,即可实现文件上传 若没有rz命令,则需用到以下命令进行安装(二选一): 适用于redhat linux: yum install lrzsz适用于centos或u…

使用Mavon-Editor编辑器上传本地图片到又拍云云存储(Vue+SpringBoot)

需求:将本地的图片上传到服务器或者云存储中,考虑之后,这里我选的是上传到又拍云云存储。 技术背景: 前端:VueAjax 后端:SpringBoot 存储:又拍云云存储原理:Mavon-Editor编辑器有两个…

大模型框架LangChain开发实战(二)

一、关于数据的准备及项目背景 Notion提供了团队管理的功能,方便团队成员进行在线协作办公,提高交互效率,notion上面的数据可能包括项目的数据,进度管理的数据,企业服务的数据等等,这里使用了从notion网站…

【校招VIP】产品分析能力之用户画像出发

考点介绍: 用户行为和交互是产品经理能力的重要部分,在校招中,基于用户画像的分析题和设计题也是高频考点。 『产品分析能力之用户画像出发』相关题目及解析内容可点击文章末尾链接查看! 一、考点题目 1. 爱奇艺中搜索关键词“…

【C++ 学习⑮】- 模板进阶

目录 一、必须使用 typename 的场景 二、非类型模板参数 三、模板的特化 3.1 - 函数模板特化 3.2 - 类模板特化 3.2.1 - 全特化 3.2.2 - 偏特化 四、类模板分离式编译 4.1 - 分离编译的概念 4.2 - 类模板分离式的问题 4.3 - 解决方案 一、必须使用 typename 的场景 …

shell 基础3

在第一行后面追加内容 在第3行后面追加内容 在每行前面加 在第四行前面加入 -i表示添加在文本中 在每个22后面加 $a 在文件最后一行追加 匹配到每个包含22的行,并在之前加 把第7行整行替换 将所有匹配22的行替换 删除第5行 隔行删除,删除奇数行 删除偶数…

live555server环境搭建

live555环境搭建详解(ubuntu18.04) 1.环境依赖 openssl可选安不安 安装(选择好版本) sudo apt-get update sudo apt-get install openssl sudo apt-get install libssl-dev使用头文件是否可用时编译测试时记得链接&#xff08…

【C++入门到精通】C++入门 —— priority_queue(STL)优先队列

阅读导航 前言一、priority_queue简介1. 概念2. 特点 二、priority_queue使用1. 基本操作2. 底层结构 三、priority_queue模拟实现⭕ C代码⭕priority_queue中的仿函数 总结温馨提示 前言 ⭕文章绑定了VS平台下std::priority_queue的源码,大家可以下载了解一下&…

C#,数值计算——Ridders的多项式外推方法的计算方法与源程序

using System; namespace Legalsoft.Truffer { /// <summary> /// 通过Ridders的多项式外推方法返回函数func在点x处的导数。 /// 输入值h作为估计的初始步长&#xff1b;它不需要很小&#xff0c;而是应为x上的增量&#xff0c; /// 在此增量上func将发…

在CMD中找不到Bootrec/fixboot元素怎么办?

当您尝试在CMD中执行Bootrec/fixboot以修复Windows 7/8.1/8/10/11和Windows Server 2012等操作系统中的系统启动问题时&#xff0c;通常会遇到Bootrec/fixboot参数无效的情况。这类启动问题可能是由磁盘克隆、系统迁移、Windows更新、MBR和GPT转换等引起的。当一个问题仍然存在…

YOLO目标检测——矿石数据集图片下载分享

矿石图片&#xff0c;其中训练集包括“玄武岩”、“花岗岩”、“大理石”、“石英岩”、“煤”、“石灰石”、“砂岩”七种矿石图片。测试集包括24张相应的七种矿石图像。 数据集点击下载&#xff1a; 矿石数据集4500图片数据说明.rar

OpenGL学习路程(一)

Hello啊各位&#xff0c;鸽了挺长时间没更新&#xff0c;其实是博主找到新乐子了。 如标题所说&#xff0c;我正在学习OpenGL。 现在已经成功的调用显卡画出了一个三角形&#xff0c;这虽然不是什么大的成就&#xff0c;但已经让我很兴奋了。 我不打算在这里写出我配置openg…

Pyqt5-开源工具分解功能(文本拖拽)

开源第四篇:功能实现之拖拽功能与配置文件。 写这个功能的初衷,是因为,每次调试我都要手动敲命令,太麻烦了,想偷个懒,所以直接给这功能加上了,顺便衍生出了另一个想法,配置文件自动填写相关数据。 先看个简单的拖拽功能: 很明显吧,还是比较便捷的。所以我们本章,就在…

TextView加粗字体太粗

解决方法如下&#xff1a; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet;import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatTextView;/*** 自定义加粗…

【真人语音】讯飞星火个人声音训练及导出工具V0.2.exe

【项目背景】 小编一直在尝试着短视频技术&#xff0c;在读文案的时候经常会读错&#xff1b;所以&#xff0c;只能用微软或者剪映的文本转语音软件。 很早之前在Github上也看到过真人人声训练的开源代码&#xff0c;尝试过一番之后&#xff0c;也是以失败告终&#xff1b;就…