FreeRTOS 优先级翻转以及互斥信号量

优先级翻转:

高优先级的任务反而慢执行,低优先级的任务反而优先执行

        优先级翻转在抢占式内核中是非常常见的,但是在实时操作系统中是不允许出现优先级翻转的,因为优先级翻转会破坏任务的预期顺序,可能会导致未知的严重后果。

        在使用二值信号量的时候,经常会遇到优先级翻转的问题。

        高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度。但其他中等优先级的任务却能抢到CPU资源。从现象上看,就像是中优先级的任务比高优先级任务具有更高的优先权(即优先级翻转)

 H(高优先级)                                        M(中优先级)                                         L(低优先级)

优先级翻转实验

实验目的:在使用二值信号量的时候会存在优先级翻转的问题,本实验通过模拟的方式实现优先级翻转,观察优先级翻转对抢占式内核的影响

实验设计:将设计四个任务:start_task、high_task、 middle_task , low_task

四个任务的功能如下:

  • start_task:用来创建其他的3个任务
  • high_task:高优先级任务,会获取二值信号量,获取成功以后打印提示信息,处理完后释放信号量
  • middle_task:中等优先级任务,简单的应用任务
  • low_task:低优先级任务,同高优先级一样的操作,不同的是低优先级任务占用信号量的时间久一点

代码 :

SemaphoreHandle_t Semaphore;                /* 计数型信号量 */
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           /* 进入临界区 *//* 创建计数型信号量 */Semaphore = xSemaphoreCreateCounting(1, 1);/* 创建任务1 */xTaskCreate((TaskFunction_t )high_task,(const char*    )"high_task",(uint16_t       )TASK1_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK1_PRIO,(TaskHandle_t*  )&Task1Task_Handler);/* 创建任务2 */xTaskCreate((TaskFunction_t )middle_task,(const char*    )"middle_task",(uint16_t       )TASK2_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK2_PRIO,(TaskHandle_t*  )&Task2Task_Handler);/* 创建任务3 */xTaskCreate((TaskFunction_t )low_task,(const char*    )"low_task",(uint16_t       )TASK3_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK3_PRIO,(TaskHandle_t*  )&Task3Task_Handler);vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区 */
}void high_task(void *pvParameters)
{vTaskDelay(1000);while (1){printf("high_task 获取信号量\r\n");xSemaphoreTake(Semaphore, portMAX_DELAY);       /* 获取计数型信号量 */printf("high_task 获取成功\r\n");printf("high_task 正在运行\r\n");printf("high_task 释放信号量\r\n");xSemaphoreGive(Semaphore);                      /* 释放计数型信号量 */vTaskDelay(10000);}
}void middle_task(void *pvParameters)
{uint32_t middle_task_num = 0;   vTaskDelay(1000);while (1){for (middle_task_num=0; middle_task_num<5; middle_task_num++){printf("middle_task 正在运行\r\n");delay_ms(1000);                              /* 模拟运行,不触发任务调度 */}vTaskDelay(10000);}
}void low_task(void *pvParameters)
{uint32_t low_task_num = 0;while (1){printf("low_task 获取信号量\r\n");xSemaphoreTake(Semaphore, portMAX_DELAY);       /* 获取计数型信号量 */printf("low_task 获取成功\r\n");for (low_task_num=0; low_task_num<5; low_task_num++){printf("low_task 正在运行\r\n");delay_ms(1000);                              /* 模拟运行,不触发任务调度 */}printf("low_task 释放信号量\r\n");xSemaphoreGive(Semaphore);                      /* 释放计数型信号量 */vTaskDelay(1000);}
}

实验结果:

实验注意:延迟时间,确保有足够的延迟时间使中优先级任务和低优先级任务运行 

 

 互斥信号量

        互斥信号量其实就是一个拥有优先级继承的二值信号量,在同步的应用中二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中!

优先级继承:

        当一个互斥信号量正在被一个低优先级的任务持有时, 如果此时有个高优先级的任务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级。

         此时任务H的阻塞时间仅仅是任务L 的执行时间,将优先级翻转的危害降到了最低。

 

 优先级继承并不能完全的消除优先级翻转的问题,它只是尽可能的降低优先级翻转带来的影响

注意:互斥信号量不能用于中断服务函数中,原因如下:

  1. 互斥信号量有任务优先级继承的机制, 但是中断不是任务,没有任务优先级, 所以互斥信号量只能用与任务中,不能用于中断服务函数。
  2. 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。

互斥信号量相关API函数

使用互斥信号量:首先将 宏 configUSE_MUTEXES 置一

使用流程:创建互斥信号量\rightarrow(task)获取信号量 \rightarrow(give)释放信号量

创建互斥信号量函数:

函数

描述

xSemaphoreCreateMutex()

使用动态方法创建互斥信号量。

xSemaphoreCreateMutexStatic()

使用静态方法创建互斥信号量。

返回值

描述

NULL

创建失败

其他值

创建成功返回互斥信号量的句柄

 此函数用于创建互斥信号量 

#define   xSemaphoreCreateMutex (   )                     \xQueueCreateMutex     (queueQUEUE_TYPE_MUTEX )

互斥信号量的释放和获取函数与二值信号量相同 !只不过互斥信号量不支持中断中调用 

注意:创建互斥信号量时,会主动释放一次信号量 

互斥信号量实验 

实验目的:在优先级翻转实验的基础,加入互斥信号量,解决优先级翻转问题

实验设计:将优先级翻转所用到的信号量函数,修改成互斥信号量即可,通过串口打印提示信息

代码:

整体和上份没有太大区别,仅是使用了 互斥信号量

SemaphoreHandle_t MutexSemaphore;                /* 互斥信号量 */
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           /* 进入临界区 *//* 创建互斥信号量 */MutexSemaphore = xSemaphoreCreateMutex();/* 创建任务1 */xTaskCreate((TaskFunction_t )high_task,(const char*    )"high_task",(uint16_t       )TASK1_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK1_PRIO,(TaskHandle_t*  )&Task1Task_Handler);/* 创建任务2 */xTaskCreate((TaskFunction_t )middle_task,(const char*    )"middle_task",(uint16_t       )TASK2_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK2_PRIO,(TaskHandle_t*  )&Task2Task_Handler);/* 创建任务3 */xTaskCreate((TaskFunction_t )low_task,(const char*    )"low_task",(uint16_t       )TASK3_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK3_PRIO,(TaskHandle_t*  )&Task3Task_Handler);vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区 */
}void high_task(void *pvParameters)
{vTaskDelay(1000);while (1){printf("high_task 获取信号量\r\n");xSemaphoreTake(MutexSemaphore, portMAX_DELAY);       /* 获取计数型信号量 */printf("high_task 获取成功\r\n");printf("high_task 正在运行\r\n");printf("high_task 释放信号量\r\n");xSemaphoreGive(MutexSemaphore);                      /* 释放计数型信号量 */vTaskDelay(10000);}
}void middle_task(void *pvParameters)
{uint32_t middle_task_num = 0;   vTaskDelay(1000);while (1){for (middle_task_num=0; middle_task_num<5; middle_task_num++){printf("middle_task 正在运行\r\n");delay_ms(1000);                              /* 模拟运行,不触发任务调度 */}vTaskDelay(10000);}
}void low_task(void *pvParameters)
{uint32_t low_task_num = 0;while (1){printf("low_task 获取信号量\r\n");xSemaphoreTake(MutexSemaphore, portMAX_DELAY);       /* 获取计数型信号量 */printf("low_task 获取成功\r\n");for (low_task_num=0; low_task_num<5; low_task_num++){printf("low_task 正在运行\r\n");delay_ms(1000);                              /* 模拟运行,不触发任务调度 */}printf("low_task 释放信号量\r\n");xSemaphoreGive(MutexSemaphore);                      /* 释放计数型信号量 */vTaskDelay(1000);}
}

实验结果 :

总结来说 

         FreeRTOS中的互斥信号量通过优先级继承机制有效地减少了优先级翻转的影响,从而提高了系统的实时性和响应性。这一机制使得低优先级任务在持有关键资源时,其优先级会被临时提升,以便尽快释放资源给高优先级任务,从而保证高优先级任务能尽快获得资源,减少不必要的延迟。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OPenCV结构分析与形状描述符(2)计算轮廓周长的函数arcLength()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算轮廓的周长或曲线的长度。 该函数计算曲线的长度或闭合轮廓的周长。 如果曲线是闭合的&#xff08;即首尾相连&#xff09;&#xff0c;则计…

【数据结构】单链表的应用

1.移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 思路&#xff1a; 创建新链表&#xff0c;找值不为val的节点&#xff0c;尾插到新链表中 /*** Definition for singly-li…

OpenAI发布GPT-4o mini,3.5从此退出历史舞台?

随着OpenAI在2024年7月18日正式发布GPT-4o Mini&#xff0c;无疑在科技界引发了一场新的风暴。这一创新不仅标志着GPT-3.5模型正式退出历史舞台&#xff0c;更预示着人工智能在自然语言处理领域迈入了一个全新的时代。 之前速度最快的模型一直是GPT3.5&#xff0c;随着后来的GP…

基于大数据的科研热点分析与挖掘系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 科研活动的快速发展产生了大量的学术文献&#xff0c;如何从这些文献中提炼出有价值的科研热点和趋势成为了一个重要的问题。本项目旨在开发一个基于大数据的科研热点分析可视化系统&#xff0c;采…

python tkinter 文本类组件

Label组件 Label(win,text文本,justifycenter) win指定Label组件的父容器&#xff1b;text指定标签中的文本&#xff1b;justify指定标签中拥有多行文本时&#xff0c;最后一行文本的对齐方式。 from tkinter import * from PIL import Image,ImageTkroot Tk() root.title(…

水晶连连看 - 无限版软件操作说明书

水晶连连看 – 无限版游戏软件使用说明书 文章目录 水晶连连看 – 无限版游戏软件使用说明书1 引言1.1 编写目的1.2 项目名称1.3 项目背景1.4 项目开发环境 2 概述2.1 目标2.2 功能2.3 性能 3 运行环境3.1 硬件3.2 软件 4 使用说明4.1 游戏开始界面4.2 游戏设定4.2.1 游戏帮助4…

「大数据分析」图形可视化,如何选择大数据可视化图形?

​图形可视化技术&#xff0c;在大数据分析中&#xff0c;是一个非常重要的关键部分。我们前期通过数据获取&#xff0c;数据处理&#xff0c;数据分析&#xff0c;得出结果&#xff0c;这些过程都是比较抽象的。如果是非数据分析专业人员&#xff0c;很难清楚我们这些工作&…

前端常用工具网站分享:MemFire Cloud,懒人开发者的福音

你是否曾梦想过&#xff0c;有那么一款工具&#xff0c;能够让你像变魔术一样快速搭建起一个应用&#xff0c;而无需深陷复杂的后端搭建和接口开发的泥潭&#xff1f;今天&#xff0c;我要为你介绍的&#xff0c;就是这样一个神奇的存在——MemFire Cloud&#xff0c;一款专为懒…

13款常用AI编程工具

AI编程工具的选择和使用&#xff0c;主要取决于具体的项目需求、编程语言、以及AI任务的类型&#xff08;如机器学习、自然语言处理、计算机视觉等&#xff09;。下面是一些广泛使用的AI编程工具合集&#xff0c;涵盖了从开发、训练、到部署的各个环节&#xff1a; Jupyter Not…

随手记:小程序体积超出2M包大小如何优化

小程序的包体积限制是2M&#xff0c;超出包大小如何优化 先简单列出&#xff0c;最近比较忙&#xff0c;后续优化明细&#xff0c;有着急的先留言踢我 1.分包 留几个主要的页面体积小的&#xff0c;剩下的在page.json中拆到subpackages中&#xff0c;简单举个例子 "page…

【C++ Primer Plus习题】10.8

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream> #include "List.h" …

[数据集][目标检测]水面垃圾检测数据集VOC+YOLO格式2027张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2027 标注数量(xml文件个数)&#xff1a;2027 标注数量(txt文件个数)&#xff1a;2027 标注…

MarkdownEditor 配置以及使用

MarkdownEditor 配置以及使用 MarkdownEditor是一款基于浏览器的 Markdown 编辑器&#xff0c;虽然他是独立软件&#xff0c;但该软件内嵌一个浏览器。功能非常简单实用、反应速度很快&#xff0c;号称是Markdown领域的NotePad&#xff08;记事本&#xff09;。 MarkdownEdit…

JDBC与数据库之间的操作(增删改查、获取主键、业务逻辑分离、属性文件配置)

参考视频哔哩哔哩 1、Service和Servicelmpl的概念 java中service和servicelmpl是常见的代码组织方式 Service是指业务逻辑的接口&#xff0c;定义了系统对外提供的功能。Servicelmpl是Service接口的具体实现&#xff0c;实现了具体的业务逻辑。 Service和Servicelmpl的好处…

SpinalHDL之数据类型(一)

本文作为SpinalHDL学习笔记第五十四篇,介绍SpinalHDL的Bool数据类型。 SpinalHDL技术交流QQ群: Note: 1.本群是个人技术交流群,不是什么官方答疑群; 2.提问是你的权利,但回答不是别人的义务; 3.可以潜水,不能灌水; 4.请文明交流,做这行的都算高层次人才,希望你…

黑神话悟空背后的技术揭秘与代码探秘

《重塑神话&#xff1a;黑神话悟空背后的技术揭秘与代码探秘》 引言 在国产游戏领域&#xff0c;《黑神话:悟空》无疑是一颗璀璨的明星&#xff0c;它不仅融合了深厚的中国文化元素&#xff0c;更在技术上实现了诸多突破&#xff0c;为玩家带来了前所未有的沉浸式体验。本文将…

sqli-lab靶场学习(一)——Less1-4

前言 最近一段时间想切入安全领域&#xff0c;因为本身有做数据库运维工作&#xff0c;就打算从sql注入方向切入。而sql注入除了学习日常书本上的概念外&#xff0c;需要有个实践的环境&#xff0c;刚好看到sqli-lab这个靶场&#xff0c;就打算先用这个来学习。 安装部署 网上…

HTTP“请求”和“响应”的报头及正文详解

目录 一、请求 "报头" (header) 二、请求 "正文" (body) 2.1 application/x-www-form-urlencoded 2.2 multipart/form-data 2.3 application/json 三、HTTP 响应状态码 四、响应 "报头" (header) 五、响应 "正文" (body) 5.1…

微信小程序实践案例

参考视频&#xff1a; https://www.bilibili.com/video/BV1834y1676P/?p36&spm_id_frompageDriver&vd_sourceb604c19516c17da30b6b1abb6c4e7ec0 前期准备 1、新建三个页面 "pages": ["pages/home/home","pages/message/message",&quo…

智慧交通基于yolov8的井盖异常检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 智慧交通中的井盖异常检测系统&#xff0c;基于先进的YOLOv8算法&#xff0c;为城市基础设施的安全管理提供了强有力的技术支持。该系统通过集成YOLOv8的深度学习技术&#xff0c;实现了对道路井盖状态的实时、精准监测。 YOLOv8以其高效、准确的特点&#xff0…