FreeRTOS(互斥信号量)

news2024/11/25 4:43:12

 资料来源于硬件家园:资料汇总 - FreeRTOS实时操作系统课程(多任务管理)

目录

一、互斥信号量的定义与应用

1、互斥信号量的定义

2、互斥信号量的应用

3、简要了解递归互斥信号量

二、优先级翻转问题

1、运行条件

2、优先级翻转编程测试

三、互斥信号量的运作机制

四、互斥信号量常用的API函数

 1、互斥信号量的典型流程与API

2、互斥信号量创建与删除

3、互斥信号量释放

4、互斥信号量获取

五、互斥信号量的应用编程

1、使能互斥信号量

 2、创建互斥信号量

 3、创建三个优先级不同任务验证


一、互斥信号量的定义与应用

1、互斥信号量的定义

前面学过,取值只有0与1两种状态的信号量称之为二值信号量。 而互斥信号量是一种特殊的二值信号量,具有防止优先级翻转的特性。

创建互斥信号量时,系统会为创建的互斥信号量分配内存,互斥信号量创建完成后的示意图如下:

图片

2、互斥信号量的应用

在嵌入式操作系统中,互斥信号量用于临界资源的独占式访问,只能用于任务与任务间,因为其特有的优先级继承机制只能在任务中起作用,在中断的上下文环境毫无意义。

应用场景:

比如有两个任务需要通过同一串口发送数据,其硬件资源只有一个,那么两个任务不能同时发送,否则会导致数据错误。此时就可以用互斥信号量对串口资源进行保护,当任务1正在使用串口发送数据时,互斥信号量变为无效,任务2无法使用串口,任务2必须等待互斥信号量有效(任务1释放信号量),才能获得串口使用权,进而发送数据。

3、简要了解递归互斥信号量

递归互斥信号量是一种特殊的互斥信号量,支持拥有该信号量使用权的任务重复多次获取,而不会死锁。 任务成功获取几次递归互斥信号量,就要返还几次,在此之前,递归互斥信号量都处于无效状态。

二、优先级翻转问题

使用互斥信号量,可以有效的防止优先级翻转问题。

图片

1、运行条件

 创建 3 个任务 Task1,Task2 和 Task3,优先级分别为 3,2,1。也就是 Task1 的优先级最高。 

 任务 Task1 和 Task3 互斥访问串口打印 printf,采用二值信号实现互斥访问。

 起初 Task3 通过二值信号量正在调用 printf,被任务 Task1 抢占,开始执行任务 Task1,也就是上图的起始位置。

 任务 Task1 运行的过程需要调用函数 printf,发现任务 Task3 正在调用,任务 Task1 会被挂起,等待 Task3 释放函数 printf。 

 在调度器的作用下,任务 Task3 得到运行,Task3 运行的过程中,由于任务 Task2 就绪,抢占了 Task3的运行。优先级翻转问题就出在这里了,从任务执行的现象上看,任务 Task1 需要等待 Task2 执行完毕才有机会得到执行,这个与抢占式调度正好反了,正常情况下应该是高优先级任务抢占低优先级任务的执行,这里成了高优先级任务 Task1 等待低优先级任务 Task2 完成。这种情况被称之为优先级翻转问题。 

 任务 Task2 执行完毕后,任务 Task3 恢复执行,Task3 释放互斥资源后,任务 Task1 得到互斥资源,从而可以继续执行。

2、优先级翻转编程测试

三、互斥信号量的运作机制

互斥量处理不同任务对临界资源的访问时,任务要获得互斥量才能进行资源访问。一旦有任务成功获得了互斥量,则互斥量立即变为闭锁状态,此时其他任务会因为获取不到互斥量而不能访问这个资源。任务会根据用户自定义的等待时间进行等待,直到互斥量被持有的任务释放,其他任务才能获取互斥量从而得以访问该临界资源。此时互斥量再次上锁,如此一来就可以确保每个时刻只有一个任务正在访问这个临界资源,保证了临界资源操作的安全性,具体如下图所示。

图片

①:因为互斥量具有优先级继承机制,一般选择使用互斥量对资源进行保护。当采用互斥量保护的资源被占用时,无论是什么优先级的任务,想要使用该资源都会被阻塞

②:假如正在使用该资源的任务1比阻塞中的任务2的优先级低,那么任务1的优先级将被系统临时提升到与高优先级任务2相等(任务1的优先级从L变成H),这个就是所谓的优先级继承,这样就有效地防止了优先级翻转问题,因为此时优先级介于任务1与任务2之间的任务,抢占不了CPU。

③:当任务1使用完资源之后,释放互斥量,此时任务1的优先级会从H变回原来的L

④~⑤:任务2此时可以获得互斥量,然后进行资源的访问,当任务2访问了资源时,该互斥量的状态又变为闭锁状态,其他任务无法获取互斥量。

四、互斥信号量常用的API函数

 1、互斥信号量的典型流程与API

> 创建互斥信号量  xSemaphoreCreateMutex()

> 释放互斥信号量  xSemaphoreGive()

> 获取互斥信号量  xSemaphoreTake()

> 删除互斥信号量  vSemaphoreDelete()

2、互斥信号量创建与删除

互斥信号量控制块(句柄)

如下图:二值信号量的句柄为消息队列的句柄,因为二值信号量是一种长度为1,消息大小为0的特殊消息队列

图片

图片

图片

互斥信号量创建

函数原型:SemaphoreHandle_t xSemaphoreCreateMutex( void )

函数描述:函数 xSemaphoreCreateMutex 用于创建互斥信号量。

 返回值,如果创建成功会返回互斥信号量的句柄,如果由于 FreeRTOSConfig.h 文件中 heap 大小不足,无法为此互斥信号量提供所需的空间会返回 NULL。

使用这个函数要注意以下问题

1. 使用此函数要在 FreeRTOSConfig.h 文件中使能宏定义:#define configUSE_MUTEXES 1

说明:此函数基于消息队列函数实现:

图片

应用举例:

图片

互斥信号量删除

函数原型:void vSemaphoreDelete( SemaphoreHandle_t xSemaphore ); /* 信号量句柄 */

函数描述:函数 vSemaphoreDelete可用于删除互斥信号量。 

3、互斥信号量释放

函数原型:xSemaphoreGive( SemaphoreHandle_t xSemaphore ); /* 信号量句柄 */

函数描述:函数 xSemaphoreGive 用于在任务代码中释放信号量。

 第 1 个参数是信号量句柄。

 返回值,如果信号量释放成功返回 pdTRUE,否则返回 pdFALSE,因为信号量的实现是基于消息队列,返回失败的主要原因是消息队列已经满了。

使用这个函数要注意以下问题:

1. 此函数是用于任务代码中调用的,不可以在中断服务程序中调用此函数。

2. 使用此函数前,一定要保证用函数 xSemaphoreCreateBinary(), xSemaphoreCreateMutex() 或者xSemaphoreCreateCounting()创建了信号量。

3. 此函数不支持使用 xSemaphoreCreateRecursiveMutex()创建的信号量。

应用举例:

图片

4、互斥信号量获取

函数原型:xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );         函数描述:函数 xSemaphoreTake 用于在任务代码中获取信号量。 

 第 1 个参数是信号量句柄。 

 第 2 个参数是没有信号量可用时,等待信号量可用的最大等待时间,单位系统时钟节拍。 返回值,如果创建成功会获取信号量返回 pdTRUE,否则返回 pdFALSE。

使用这个函数要注意以下问题:

1. 此函数是用于任务代码中调用的,不可以在中断服务程序中调用此函数。

2. 如果消息队列为空且第 2 个参数为 0,那么此函数会立即返回。

3. 如果用户将 FreeRTOSConfig.h 文件中的宏定义 INCLUDE_vTaskSuspend 配置为 1 且第 2 个参数配置为 portMAX_DELAY,那么此函数会永久等待直到信号量可用。

应用举例:

图片

五、互斥信号量的应用编程

1、使能互斥信号量

 2、创建互斥信号量

 3、创建三个优先级不同任务验证

  if(myMutex01Handle==NULL)
	  HAL_UART_Transmit(&huart2, (uint8_t*)"创建互斥信号量成功 \r\n",16, HAL_MAX_DELAY);
  else
	  HAL_UART_Transmit(&huart2, (uint8_t*)"创建互斥信号量失败 \r\n",16, HAL_MAX_DELAY);
void StartTask03(void const * argument)
{
  /* USER CODE BEGIN StartTask03 */
	BaseType_t xResult;
  /* Infinite loop */
  for(;;)
  {
	  HAL_UART_Transmit(&huart2, (uint8_t*)"H_StartTask03获取互斥信号量...\r\n",32, HAL_MAX_DELAY);
	  xResult=xSemaphoreTake(myMutex01Handle,portMAX_DELAY);

	  if(xResult==pdTRUE)
	  {
		  HAL_UART_Transmit(&huart2, (uint8_t*)"H_StartTask03 Running...\r\n",28, HAL_MAX_DELAY);
	  }
	  HAL_UART_Transmit(&huart2, (uint8_t*)"H_StartTask03 释放互斥信号量...\r\n",35, HAL_MAX_DELAY);
	  xResult=xSemaphoreGive(myMutex01Handle);
    osDelay(500);
  }
  /* USER CODE END StartTask03 */
}
void StartTask04(void const * argument)
{
  /* USER CODE BEGIN StartTask04 */
  /* Infinite loop */
  for(;;)
  {
	  HAL_UART_Transmit(&huart2, (uint8_t*)"M_StartTask04 runing...\r\n",27, HAL_MAX_DELAY);
    osDelay(500);
  }
  /* USER CODE END StartTask04 */
}
void StartTask05(void const * argument)
{
  /* USER CODE BEGIN StartTask05 */
	BaseType_t xResult;
  /* Infinite loop */
  for(;;)
  {
	  HAL_UART_Transmit(&huart2, (uint8_t*)"L_StartTask03获取互斥信号量...\r\n",27, HAL_MAX_DELAY);
	  xResult=xSemaphoreTake(myMutex01Handle,portMAX_DELAY);

	  if(xResult==pdTRUE)
	  {
		  HAL_UART_Transmit(&huart2, (uint8_t*)"L_StartTask03 Running...\r\n",28, HAL_MAX_DELAY);
	  }

	  HAL_Delay(3000);
	  HAL_UART_Transmit(&huart2, (uint8_t*)"L_StartTask03 释放互斥信号量...\r\n",28, HAL_MAX_DELAY);
	  xResult=xSemaphoreGive(myMutex01Handle);
    osDelay(500);
  }
  /* USER CODE END StartTask05 */
}

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

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

相关文章

[HDLBits] Exams/m2014 q3

Consider the function f shown in the Karnaugh map below. Implement this function. d is dont-care, which means you may choose to output whatever value is convenient. //empty

[HDLBits] Exams/2012 q1g

Consider the function f shown in the Karnaugh map below. Implement this function. (The original exam question asked for simplified SOP and POS forms of the function.) //

文本三剑客之grep命令和awk命令 1.0 版本

grep awk 1.grep命令1.1 基本格式1.2 常用选项 2.awk命令2.1 awk工作原理2.2 awk命令格式2.3 awk常用内置变量 1.grep命令 1.1 基本格式 grep [选项]… 查找条件 目标文件1.2 常用选项 选项功能 -m [ x ]匹配x次 后停止,x为具体数字-v取反 -i忽略字符大小写 -n显示匹配的 …

GrapeCity Documents for Excel, Java Edition Crack

GrapeCity Documents for Excel, Java Edition Crack 增加了对SpreadJS.sjs文件格式的支持: 更快地将大型Microsoft Excel文件转换为.sjs格式。 使用较小的占用空间保存导出的文件。 将Excel/SpreadJS功能导入SpreadJS/从SpreadJS导出。 从.sjs文件中压缩的JSON文件…

小程序发布注意事项

1、使用HBuildx的 发布 功能发布小程序,因为编译完的代码目录不是同一个 如果使用 运行 到小程序,最后发布的版本会显示”无法连接本地服务器“ 2、使用unicloud的云服务 uniCloud发行 | uni-app官网 阿里云的unicloud的话,使用request域名…

Docker启动、停止、删除容器的相关指令

关闭容器指令: docker stop name启动命令: docker start name删除容器: docker rm name 或 id查看所有容器id: docker ps -aq删除所有容器: docker rm docker ps -aq开启着的容器是不能被删除的。 查看容器信息&…

华为OD机试 - 最长连续子序列 - 双指针(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述备注 四、双指针1、双指针是什么?2、Java双指针算法适合解决哪些问题? 五、解题思路六、Java算法源码七、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专…

GUI、多线程编程、网络编程简介

GUI、多线程编程、网络编程简介 文章目录 GUI简介什么是GUIGUI有什么用使用方法 多线程编程什么是多线程编程多线程编程有什么用提高程序的响应能力提高程序的性能实现异步编程并发数据访问和共享资源实现复杂的算法和任务分解 进行多线程编程的步骤 网络编程什么是网络编程网络…

day6 STM32时钟与定时器

STM32时钟系统的概述 概念 时钟系统是由振荡器(信号源)、定时唤醒器、分频器等组成的电路。 常用的信号有晶体振荡器和RC振荡器。 意义 时钟是嵌入式系统的脉搏,处理器内核在时钟驱动下完成指令执行,状态变换等动作&#xff…

迪瑞克斯拉算法

迪锐克斯拉算法 简单来说就是在有向图中,给定一个图中具体的出发点,从这个点出发能够到达的所有的点,每个点的最短距离是多少。到不了的点,距离则是正无穷。有向,无负权重,可以有环。 所以说,迪…

Linux 终端命令之文件浏览(4) head, tail

Linux 文件浏览命令 cat, more, less, head, tail,此五个文件浏览类的命令皆为外部命令。 hannHannYang:~$ which cat /usr/bin/cat hannHannYang:~$ which more /usr/bin/more hannHannYang:~$ which less /usr/bin/less hannHannYang:~$ which head /usr/bin/he…

流量日志分析--实操

[鹤城杯 2021]流量分析 <--第一道流量分析不难,主要就是布尔盲注的流量包分析,直接查看http请求包即可我们可以通过观察看到注入成功的响应长度不同,这里成功的为978字节,失败的994字节.不要问为什么.其实也可以直接判断.978的流量比994的少了非常多 显然就是成功的(因为这里…

云计算|OpenStack|使用VMware安装华为云的R006版CNA和VRM---初步使用(二)

前言&#xff1a; 在前面一篇文章云计算|OpenStack|使用VMware安装华为云的R006版CNA和VRM---初始安装&#xff08;一&#xff09;_华为cna_晚风_END的博客-CSDN博客 介绍了基于VMware虚拟机里嵌套部署华为云的云计算&#xff0c;不过仅仅是做到了在VRM的web界面添加计算节点…

高效数据传输:轻松上手将Kafka实时数据接入CnosDB

本篇我们将主要介绍如何在 Ubuntu 22.04.2 LTS 环境下&#xff0c;实现一个KafkaTelegrafCnosDB 同步实时获取流数据并存储的方案。在本次操作中&#xff0c;CnosDB 版本是2.3.0&#xff0c;Kafka 版本是2.5.1&#xff0c;Telegraf 版本是1.27.1 随着越来越多的应用程序架构转…

keil构建STM32工程并使用proteus仿真led点灯实验

STM32单片机与51单片机有很大区别&#xff0c;不仅结构上有很大差异&#xff0c;STM32更复杂一些&#xff0c;在操作上来说&#xff0c;STM32也要复杂很多&#xff0c;51单片机上手写代码&#xff0c;可以很直接操作引脚&#xff0c;但是STM32单片机在操作引脚之前需要作很多初…

学无止境·运维高阶⑤(LVS-DR 群集 配置Nginx负载均衡)

LVS-DR 群集 && 配置Nginx负载均衡 一、LVS-DR 群集1、相关配置环境2、在RS上配置并启动脚本2.1相关脚本2.2 启动脚本&#xff0c;另一台RS同样步骤 3、LVS-DR模式配置脚本4、测试 二、Nginx负载均衡1、安装Nginx并关闭相应设置2、向主机 node2&#xff0c;node3 写入内…

【第二阶段】kotlin函数引用

针对上篇传入函数参数我们也可以重新定义一个函数&#xff0c;然后在main中调用时传入函数对象 lambda属于函数类型的对象&#xff0c;需要把普通函数变成函数类型的对象&#xff08;函数引用&#xff09;&#xff0c;使用“&#xff1a;&#xff1a;” /*** You can edit, ru…

[足式机器人]Part3机构运动微分几何学分析与综合Ch03-1 空间约束曲线与约束曲面微分几何学——【读书笔记】

本文仅供学习使用 本文参考&#xff1a; 《机构运动微分几何学分析与综合》-王德伦、汪伟 《微分几何》吴大任 Ch01-4 平面运动微分几何学 3.1 空间曲线微分几何学概述3.1.1 矢量表示3.1.2 Frenet标架 连杆机构中的连杆与连架杆构成运动副&#xff0c;该运动副元素的特征点或特…

二十二、策略模式

目录 1、项目需求2、传统方案解决鸭子问题的分析和代码实现3、传统方式实现存在的问题分析和解决方案4、策略模式基本介绍5、使用策略模式解决鸭子问题6、策略模式的注意事项和细节7、策略模式的使用场景 以具体项目来演示为什么需要策略模式&#xff0c;策略模式的优点&#x…

GitHub 如何部署写好的H5静态页面

感谢粉皮zu的私信&#xff0c;又有素材写笔记了。(●’◡’●) 刚好记录一下我示例代码的GitHub部署配置&#xff0c;以便于后期追加仓库。 效果 环境 gitwin 步骤 第一步 新建仓库 第二步 拉取代码 将仓库clone到本地 git clone 地址第三步 部署文件 新建.github\workflo…