FreeRTOS ~(七)互斥量 ~ (2/3)互斥量解决优先级反转问题

news2024/9/22 23:24:34

前情提要
FreeRTOS ~(四)同步互斥与通信 ~ (2/3)互斥的缺陷
FreeRTOS ~(五)队列的常规使用 ~ (2/5)队列解决互斥缺陷
FreeRTOS ~(六)信号量 ~ (2/3)信号量解决互斥缺陷
FreeRTOS ~(七)互斥量 ~ (1/3)互斥量解决互斥缺陷
互斥量解决优先级反转问题

上述的几篇文章说明了互斥的缺陷及一些解决方法,但是却没有解决一个问题:
互斥的两个任务的优先级反转问题.
为了说明说明是优先级反转,这里设置一个例子来实际操作一下;
举例说明:
创建三个任务,优先级不同,
如:
高优先级的优先级是3;
中优先级的优先级是2;
低优先级的优先级是1;
高优先级与低优先级都要使用到信号量,而中优先级不使用信号量,这里使用二值信号量来解决互斥问题;
高优先级执行后主动让自己Dealy 10ms,然后去获取信号量(take)
中优先级执行后主动让自己Delay 30ms,
低优先级任务则先获取信号量(take),然后执行一段较为耗时的打印工作,执行完成后,释放信号量(give)
通过设置相应的标志位(Flag),利用逻辑分析仪来观察Task执行情况.
代码如下:
static volatile uint8_t flagLPTaskRun = 0;	/* 低优先级任务执行标志位 */
static volatile uint8_t flagMPTaskRun = 0;	/* 中优先级任务执行标志位 */
static volatile uint8_t flagHPTaskRun = 0;	/* 高优先级任务执行标志位 */
static void vLPTask( void *pvParameters );	/* 低优先级任务声明 */
static void vMPTask( void *pvParameters );	/* 中优先级任务声明 */
static void vHPTask( void *pvParameters );	/* 高优先级任务声明 */
/*-----------------------------------------------------------*/
/* 互斥量/二进制信号量句柄 */
SemaphoreHandle_t  xLock;
/*-----------------------------------------------------------*/
int main( void )
{
	prvSetupHardware();
    /* 创建互斥量/二进制信号量 */
    xLock = xSemaphoreCreateBinary();
	xSemaphoreGive(xLock);
	
	if( xLock != NULL )
	{
		/* 创建3个任务: LP,MP,HP(低/中/高优先级任务) */
		xTaskCreate( vLPTask, "LPTask", 1000, NULL, 1, NULL );
		xTaskCreate( vMPTask, "MPTask", 1000, NULL, 2, NULL );
		xTaskCreate( vHPTask, "HPTask", 1000, NULL, 3, NULL );
		/* 启动调度器 */
		vTaskStartScheduler();
	}
	else
	{
		/* 无法创建互斥量/二进制信号量 */
	}
	/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
	return 0;
}
/*-----------------------------------------------------------*/
static void vLPTask( void *pvParameters )
{
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 10UL );	
	uint32_t i;
	char c = 'A';
	printf("LPTask start\r\n");
	/* 无限循环 */
	for( ;; )
	{	
		/* 标志位表明正在执行的任务是低优先级任务 */
		flagLPTaskRun = 1;
		flagMPTaskRun = 0;
		flagHPTaskRun = 0;
		/* 获得互斥量/二进制信号量 */
		xSemaphoreTake(xLock, portMAX_DELAY);
		/* 耗时很久 */
		printf("LPTask take the Lock for long time");
		for (i = 0; i < 500; i++) 
		{
			flagLPTaskRun = 1;
			flagMPTaskRun = 0;
			flagHPTaskRun = 0;
			printf("%c", c + i);
		}
		printf("\r\n");
		/* 释放互斥量/二进制信号量 */
		xSemaphoreGive(xLock);
		vTaskDelay(xTicksToWait);
	}
}
/*-----------------------------------------------------------*/
static void vMPTask( void *pvParameters )
{
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 30UL );	

	flagLPTaskRun = 0;
	flagMPTaskRun = 1;
	flagHPTaskRun = 0;
	printf("MPTask start\r\n");
	/* 让LPTask、HPTask先运行 */	
	vTaskDelay(xTicksToWait);
	/* 无限循环 */
	for( ;; )
	{	
		/* 标志位表明正在执行的任务是中优先级任务 */
		flagLPTaskRun = 0;
		flagMPTaskRun = 1;
		flagHPTaskRun = 0;
	}
}
/*-----------------------------------------------------------*/
static void vHPTask( void *pvParameters )
{
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 10UL );	
	/* 标志位表明正在执行的任务是高优先级任务 */
	flagLPTaskRun = 0;
	flagMPTaskRun = 0;
	flagHPTaskRun = 1;
	printf("HPTask start\r\n");
	/* 主动进入阻塞态,10ms,让LPTask先运行 */	
	vTaskDelay(xTicksToWait);
	/* 无限循环 */
	for( ;; )
	{	
		flagLPTaskRun = 0;
		flagMPTaskRun = 0;
		flagHPTaskRun = 1;
		printf("HPTask wait for Lock\r\n");
		/* 获得互斥量/二进制信号量 */
		xSemaphoreTake(xLock, portMAX_DELAY);
		flagLPTaskRun = 0;
		flagMPTaskRun = 0;
		flagHPTaskRun = 1;
		/* 释放互斥量/二进制信号量 */
		xSemaphoreGive(xLock);
	}
}
/*-----------------------------------------------------------*/

优先级反转说明

如何解决优先级反转这个问题呢?
抛弃二值信号量,使用互斥量,下面简单修改一下代码即可,因为互斥量也是特殊的信号量,使用的一些API函数是一致的,
这里只需要将信号量的创建由二进制信号量,更换为互斥量即可.
int main( void )
{
	prvSetupHardware();
    /* 创建互斥量/二进制信号量 */
    #if  0
	    xLock = xSemaphoreCreateBinary();
		xSemaphoreGive(xLock);
	#else
		xLock = xSemaphoreCreateMutex();
	#endif
	
	if( xLock != NULL )
	{
		/* 创建3个任务: LP,MP,HP(低/中/高优先级任务) */
		xTaskCreate( vLPTask, "LPTask", 1000, NULL, 1, NULL );
		xTaskCreate( vMPTask, "MPTask", 1000, NULL, 2, NULL );
		xTaskCreate( vHPTask, "HPTask", 1000, NULL, 3, NULL );
		/* 启动调度器 */
		vTaskStartScheduler();
	}
	else
	{
		/* 无法创建互斥量/二进制信号量 */
	}
	/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
	return 0;
}

优先级继承

解决优先级反转的问题,互斥量使用的方法使优先级继承.

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

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

相关文章

openpnp - 用空调压缩机改真空泵

文章目录 openpnp - 用空调压缩机改真空泵概述笔记备注END openpnp - 用空调压缩机改真空泵 概述 原来设备用的真空泵是AP200C/V 这个商品标称是48DB的噪音, 实际用的时候, 噪音很大, 应该快70DB了, 放在屋子里很吵. 如果仅仅是太吵, 可能也忍了. 关键是这个真空泵有强干扰…

JS逆向之——天翼云登录

JS逆向之——天翼云登录 前言 此文章仅用于技术交流&#xff0c;欢迎指出相关问题&#xff0c;感兴趣的可以关注我&#xff0c;有相关python逆向问题可以私信交流讨论。 目标与目的 目标网站&#xff1a;天翼云登录 目的&#xff1a;通过构建登录参数&#xff0c;完成天翼…

Qt样式表Qss

文章目录 简介基本语法使用setStyleSheet设置样式表可以设置的属性使用QtCreator设置 简介 Qss是Qt程序界面中用来设置控件的背景图片、大小、字体颜色、字体类型、按钮状态变化等属性它是用来美化UI界面。实现界面和程序的分离&#xff0c;快速切换皮肤。 学习视频 基本语法…

网络编程4——TCP协议的三大安全机制:三次握手四次挥手+确认应答机制+超时重传机制

文章目录 前言一、TCP协议段与机制TCP协议的特点TCP报头结构TCP协议的机制与特性 二、TCP协议的 连接管理机制 TCP建立连接&#xff1a;三次握手 TCP断开连接&#xff1a;四次挥手 三、TCP协议的 确认应答机制 四、TCP协议的 超时重传机制 总结 前言 本人是一个刚刚上路的I…

unordered_map 浅析

【unordered_map 浅析】 ◆● unordered_maphttps://cplusplus.com/reference/unordered_map/ &#xff08;1&#xff09;unordered_map 适用于需要快速查找&#xff0c;且不要求元素存储顺序的场景&#xff0c;尤其适合使用自定义类型作为键的情况。但是需要注意的是&#xff…

RabbitMQ的集群

新建一个虚拟机,重新安装一个RabbitMQ,不会安装的可以看下面的连接: 在Linux中安装RabbitMQ_流殇꧂的博客-CSDN博客 1.修改/etc/hosts映射文件,两台虚拟机都需要修改 vim /etc/hosts 2.修改完成后重启linux服务器: reboot 3.查看.erlang.cookie文件的位置: find / -name .erlan…

环形链表 II

题目链接 环形链表 II 题目描述 注意点 如果 pos 是 -1&#xff0c;则在该链表中没有环 解答思路 首先判断链表中是否有环&#xff0c;思路为双指针当快慢指针相遇时&#xff0c;说明链表中有环&#xff0c;假设链表中非环的节点数量为a&#xff0c;链表中环的节点数量为b…

分享一个由rust实现的openai api服务端+Android客户端

开发缘由 官方网页存在经常中途断开的问题.经常使用不同ip登录openai帐号可能会导致封号.使用开源项目chatgpt-web搭建过一个网页端,目前已被DNS污染,体验GitHub Copilot.已经使用了rust语言一段时间,打算用它写个服务端练手. 服务端 技术栈 rust Rust是一种系统级编程语言…

Elasticsearch【域的属性、分词器、Elasticsearch搜索文档】(三)-全面详解(学习总结---从入门到深化)

目录 Elasticsearch常用操作_域的属性 分词器_默认分词器 分词器_IK分词器 分词器_拼音分词器 分词器_自定义分词器 Elasticsearch搜索文档_准备工作 Elasticsearch搜索文档_搜索方式 Elasticsearch常用操作_域的属性 index 该域是否创建索引。只有值设置为true&#…

【双指针】844. 比较含退格的字符串

844. 比较含退格的字符串 解题思路 思路&#xff1a;函数deLETE的作用是处理带有退格符号的字符串。它使用双指针法来模拟字符串处理。初始时&#xff0c;慢指针slow和快指针fast都指向字符串的开头。然后&#xff0c;通过遍历字符串&#xff0c;如果当前字符不是退格符号&…

postman报错提示 Could not get any response怎么解决

目录 postman报错 解决方法&#xff1a; 在通过postman请求做接口测试的过程中&#xff0c;有时候会遇到一些报错&#xff0c;当遇到这些报错我们不要着急&#xff0c;看着具体哪里报错&#xff0c;然后进行解决 postman报错 经常使用postman的小伙伴们都应该遇到过一些报错…

工作:三菱PLC之CC-LINK通讯知识及应用

工作&#xff1a;三菱PLC之CC-LINK通讯及应用 一. cc-link接线图&#xff08;RS485两线式接线&#xff09; CC-Link Ver.1.00兼容电缆&#xff08;特性阻抗&#xff1a;100Ω&#xff0c;终端电阻100Ω&#xff09; CC-Link Ver.1.10兼容电缆&#xff08;特性阻抗&#xff1a;…

Gradio库:使用Markdown模块创建交互式应用

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

如何使用多线程

一个进程正在运行时&#xff0c;至少会有一个线程在运行。 package ChapterOne;public class Test {public static void main(String[] args) {System.out.println(Thread.currentThread().getName());//currentThread方法返回正在被执行的线程的信息//getName返回正在被执行线…

【Docker】Docker实战

文章目录 搭建nginx服务搭建私有库Busybox阿里云上创建私有库 搭建nginx服务 首先拉取nginx的镜像。 docker pull nginx:1.24.0以后台的方式运行nginx&#xff0c;并且创建一个shell进行交互。 docker run --name nginx1 --rm -it -p 8080:80 nginx:1.24.0 bash#在交互的bas…

Kubernetes_核心组件_KubeProxy_Service找到Pod与DNS解析Service/Pod

文章目录 前言一、Service找到Pod(Iptables)二、Service找到Pod(IPVS)2.1 IPVS模式原理2.2 IPVS模式实践修改为 IPVS 模式 之前修改为 IPVS 模式之中修改为 IPVS 模式之后 三、Service和Pod的DNS域名3.1 Service DNS域名3.2 Service与Deployment/StatefulSet配合Deployment普通…

无源光网络(PON)介绍及其应用

文章目录 1、无源光网络&#xff08;PON&#xff09;介绍ONU&#xff08;Optical Network Unit&#xff09;&#xff0c;光网络单元OLT&#xff08;Optical line terminal&#xff09;&#xff0c;光线路终端 2、FTTH、FTTB、FTTR组网介绍FTTR组网规划 3、局端接入设备产品介绍…

Elasticsearch 基本使用(五)查询条件匹配方式(query query_string)

查询条件匹配方式 概述querytermtermsrangematch_allmatchmatch 匹配精度问题 match_phrasematch_pharse_prefixmatch_bool_prefixmulti_match query_string简单查询一个字段在多个字段上应用同一个条件 &#xff08;类似multi_match&#xff09;在所有字段上应用同一个条件 &a…

mysql 大数据量从“.log“文件插入方法

要被插入的数据文件以及内容 表结构 插入成功&#xff0c;插入时如果有主键唯一索引&#xff0c;则按照唯一索引的大小顺序插入&#xff0c;速度会快很多

基于Spring Boot的智能学生考勤系统设计与实现(Java+spring boot+MySQL+微信小程序+

获取源码或者论文请私信博主 演示视频&#xff1a; 基于Spring Boot的智能学生考勤系统设计与实现&#xff08;Javaspring bootMySQL微信小程序人脸识别&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 后端&#xff1a;Java…