(学习日记)2024.04.05:UCOSIII第三十三节:互斥量

news2024/11/25 4:53:28

写在前面:
由于时间的不足与学习的碎片化,写博客变得有些奢侈。
但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。
既然如此
不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录,记录笔者认为最通俗、最有帮助的资料,并尽量总结几句话指明本质,以便于日后搜索起来更加容易。


标题的结构如下:“类型”:“知识点”——“简短的解释”
部分内容由于保密协议无法上传。


点击此处进入学习日记的总目录

2024.04.05:UCOSIII第三十一节:互斥量

  • 四十七、UCOSIII:互斥量
    • 1、互斥量的基本概念
    • 2、互斥量的优先级继承机制
      • 1. 优先级翻转
      • 2. 优先级继承
    • 3、互斥量应用场景
    • 4、互斥量运作机制
    • 5、互斥量控制块

四十七、UCOSIII:互斥量

1、互斥量的基本概念

互斥量又称互斥信号量(本质也是一种信号量,不具备传递数据功能),是一种特殊的二值信号量,它和信号量不同的是, 它支持互斥量所有权、递归访问以及防止优先级翻转的特性,用于实现对临界资源的独占式处理。
任意时刻互斥量的状态只有两种, 开锁或闭锁。当互斥量被任务持有时,该互斥量处于闭锁状态,这个任务获得互斥量的所有权。
当该任务释放这个互斥量时, 该互斥量处于开锁状态,任务失去该互斥量的所有权。
当一个任务持有互斥量时,其他任务将不能再对该互斥量进行开锁或持有。
持有该互斥量的任务也能够再次获得这个锁而不被挂起,这就是递归访问,也就是递归互斥量的特性,这个特性与一般的信号量有很大的不同, 在信号量中,由于已经不存在可用的信号量,任务递归获取信号量时会发生主动挂起任务最终形成死锁。

如果想要用于实现同步(任务之间或者任务与中断之间),二值信号量或许是更好的选择,虽然互斥量也可以用于任务与任务间同步, 但是互斥量更多的是用于保护资源的互锁。

用于互锁的互斥量可以充当保护资源的令牌,当一个任务希望访问某个资源时,它必须先获取令牌。
当任务使用完资源后,必须还回令牌, 以便其他任务可以访问该资源。是不是很熟悉,在我们的二值信号量里面也是一样的,用于保护临界资源,保证多任务的访问井然有序。
当任务获取到信号量的时候才能开始使用被保护的资源,使用完就释放信号量,下一个任务才能获取到信号量从而可用使用被保护的资源。
但是信号量会导致的另一个潜在问题,那就是任务优先级翻转(具体会在下文讲解)。
而μC/OS提供的互斥量可以通过优先级继承算法, 可以降低优先级翻转问题产生的影响,所以,用于临界资源的保护一般建议使用互斥量。

2、互斥量的优先级继承机制

在μC/OS操作系统中为了降低优先级翻转问题利用了优先级继承算法。
优先级继承算法是指,暂时提高某个占有某种资源的低优先级任务的优先级, 使之与在所有等待该资源的任务中优先级最高那个任务的优先级相等。而当这个低优先级任务执行完毕释放该资源时,优先级重新回到初始设定值。
因此,继承优先级的任务避免了系统资源被任何中间优先级的任务抢占。

互斥量与二值信号量最大的不同是:
互斥量具有优先级继承机制,而信号量没有。
也就是说,某个临界资源受到一个互斥量保护, 如果这个资源正在被一个低优先级任务使用,那么此时的互斥量是闭锁状态,也代表了没有任务能申请到这个互斥量,如果此时一个高优先级任务想要对这个资源进行访问, 去申请这个互斥量,那么高优先级任务会因为申请不到互斥量而进入阻塞态,那么系统会将现在持有该互斥量的任务的优先级临时提升到与高优先级任务的优先级相同, 这个优先级提升的过程叫作优先级继承。
这个优先级继承机制确保高优先级任务进入阻塞状态的时间尽可能短,以及将已经出现的“优先级翻转”危害降低到最小。

没有理解?没问题,结合过程示意图再说一遍。

1. 优先级翻转

我们知道任务的优先级在创建的时候就已经是设置好的,高优先级的任务可以打断低优先级的任务, 抢占CPU的使用权。
但是在很多场合中,某些资源只有一个,当低优先级任务正在占用该资源的时候, 即便高优先级任务也只能乖乖的等待低优先级任务使用完该资源后释放资源。
这里高优先级任务无法运行而低优先级任务可以运行的现象称为“优先级翻转”。

为什么说优先级翻转在操作系统中是危害很大?
因为在我们一开始创造这个系统的时候,我们就已经设置好了任务的优先级了,越重要的任务优先级越高。
但是发生优先级翻转,对我们操作系统是致命的危害,会导致系统的高优先级任务阻塞时间过长。

举个例子,现在有3个任务分别为H任务(High)、M任务(Middle)、L任务(Low),3个任务的优先级顺序为H任务>M任务>L任务。
正常运行的时候H任务可以打断M任务与L任务,M任务可以打断L任务,假设系统中有一个资源被保护了,此时该资源被L任务正在使用中, 某一刻,H任务需要使用该资源,但是L任务还没使用完,H任务则因为申请不到资源而进入阻塞态,L任务继续使用该资源,此时已经出现了“优先级翻转”现象, 高优先级任务在等着低优先级的任务执行。
如果在L任务执行的时候刚好M任务被唤醒了,由于M任务优先级比L任务优先级高,那么会打断L任务, 抢占了CPU的使用权,直到M任务执行完,再把CPU使用权归还给L任务,L任务继续执行,等到执行完毕之后释放该资源,H任务此时才从阻塞态解除, 使用该资源。
这个过程,本来是最高优先级的H任务,在等待了更低优先级的L任务与M任务,其阻塞的时间是M任务运行时间+L任务运行时间, 这只是只有3个任务的系统,假如很多个这样子的任务打断最低优先级的任务,那这个系统最高优先级任务岂不是崩溃了,这个现象是绝对不允许出现的, 高优先级的任务必须能及时响应。
所以,没有优先级继承的情况下,使用资源保护,其危害极大,具体见图
在这里插入图片描述

  • (1):L任务正在使用某临界资源, H任务被唤醒,执行H任务。但L任务并未执行完毕,此时临界资源还未释放。
  • (2):这个时刻H任务也要对该临界资源进行访问, 但 L任务还未释放资源,由于保护机制,H任务进入阻塞态,L任务得以继续运行,此时已经发生了优先级翻转现象。
  • (3):某个时刻M任务被唤醒,由于M任务的优先级高于L任务, M任务抢占了CPU的使用权,M任务开始运行,此时L任务尚未执行完,临界资源还没被释放。
  • (4):M任务运行结束,归还CPU使用权,L任务继续运行。
  • (5):L任务运行结束,释放临界资源,H任务得以对资源进行访问,H任务开始运行。

在这过程中,H任务的等待时间过长,这对系统来说这是很致命的。
所以这种情况不允许出现,而互斥量就是用来降低优先级翻转的产生的危害。

2. 优先级继承

假如有优先级继承呢?
那么,在H任务申请该资源的时候,由于申请不到资源会进入阻塞态,那么系统就会把当前正在使用资源的L任务的优先级临时提高到与H任务优先级相同, 此时M任务被唤醒了,因为它的优先级比H任务低,所以无法打断L任务,因为此时L任务的优先级被临时提升到H,所以当L任务使用完该资源了,进行释放, 那么此时H任务优先级最高,将接着抢占CPU的使用权, H任务的阻塞时间仅仅是L任务的执行时间,此时的优先级的危害降到了最低。具体见图
在这里插入图片描述

  • (1):L任务正在使用某临界资源,L任务正在使用某临界资源, H任务被唤醒,执行H任务。但L任务并未执行完毕,此时临界资源还未释放。
  • (2):某一时刻H任务也要对该资源进行访问,由于保护机制, H任务进入阻塞态。此时发生优先级继承,系统将L任务的优先级暂时提升到与H任务优先级相同,L任务继续执行。
  • (3):在某一时刻M任务被唤醒,由于此时M任务的优先级暂时低于L任务,所以M任务仅在就绪态,而无法获得CPU使用权。
  • (4):L任务运行完毕,H任务获得对资源的访问权,H任务从阻塞态变成运行态,此时L任务的优先级会变回原来的优先级。
  • (5):当H任务运行完毕,M任务得到CPU使用权,开始执行。
  • (6):系统正常运行,按照设定好的优先级运行。

但是使用互斥量的时候一定需要注意:
在获得互斥量后,请尽快释放互斥量,同时需要注意的是在任务持有互斥量的这段时间, 不得更改任务的优先级。
ΜC/OS的优先级继承机制不能解决优先级翻转,只能将这种情况的影响降低到最小,硬实时系统在一开始设计时就要避免优先级翻转发生。

3、互斥量应用场景

互斥量的使用比较单一,因为它是信号量的一种,并且它是以锁的形式存在。
在初始化的时候,互斥量处于开锁的状态,而被任务持有的时候则立刻转为闭锁的状态。

互斥量更适合于:

  • 可能会引起优先级翻转的情况。
  • 任务可能会多次获取互斥量的情况下,这样可以避免同一任务多次递归持有而造成死锁的问题。

多任务环境下往往存在多个任务竞争同一临界资源的应用场景,互斥量可被用于对临界资源的保护从而实现独占式访问。另外, 互斥量可以降低信号量存在的优先级翻转问题带来的影响。

比如有两个任务需要对串口进行发送数据,其硬件资源只有一个,那么两个任务肯定不能同时发送啦,不然导致数据错误,那么, 就可以用互斥量对串口资源进行保护。
当一个任务正在使用串口的时候,另一个任务则无法使用串口,等到任务使用串口完毕之后,另外一个任务才能获得串口的使用权。

另外需要注意的是互斥量不能在中断服务函数中使用,因为其特有的优先级继承机制只在任务起作用,而在中断的上下文环境中毫无意义。

4、互斥量运作机制

多任务环境下会存在多个任务访问同一临界资源的场景,该资源会被任务独占处理。
其他任务在资源被占用的情况下不允许对该临界资源进行访问, 这个时候就需要用到μC/OS的互斥量来进行资源保护,那么互斥量是怎样来避免这种冲突?

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

  • (1):因为互斥量具有优先级继承机制,一般选择使用互斥量对资源进行保护, 如果资源被占用的时候,无论是什么优先级的任务想要使用该资源都会被阻塞。
  • (2):假如正在使用该资源的任务1比阻塞中的任务2的优先级还低, 那么任务1将被系统临时提升到与高优先级任务2相等的优先级(任务1的优先级从L 变成H)。
  • (3):当任务1使用完资源之后,释放互斥量,此时任务1的优先级会从H变回原来的L。
  • (4)-(5):任务2此时可以获得互斥量,然后进行资源的访问, 当任务2访问了资源的时候,该互斥量的状态又为闭锁状态,其他任务无法获取互斥量。

5、互斥量控制块

μC/OS的互斥量由多个元素组成,在互斥量被创建时,需要由我们自己定义互斥量(也可以称之为互斥量句柄)。
因为它是用于保存互斥量的一些信息的, 其数据结构OS_MUTEX除了互斥量必须的一些基本信息外,还有指向任务控制块的指针OwnerTCBPtr、任务优先级变量OwnerOriginalPrio、 PendList链表与OwnerNestingCtr变量等,为的是方便系统来管理互斥量。
示意图具体见图:
在这里插入图片描述

其数据结构具体如何:

struct  os_mutex

{
/* ------------------ GENERIC  MEMBERS ------------------ */
    OS_OBJ_TYPE          Type;                 (1)
    CPU_CHAR            *NamePtr;              (2)
    OS_PEND_LIST         PendList;             (3)

#if OS_CFG_DBG_EN > 0u
    OS_MUTEX            *DbgPrevPtr;
    OS_MUTEX            *DbgNextPtr;
    CPU_CHAR            *DbgNamePtr;
#endif
/* ------------------ SPECIFIC MEMBERS ------------------ */
    OS_TCB              *OwnerTCBPtr;               (4)
    OS_PRIO              OwnerOriginalPrio; (5)
    OS_NESTING_CTR       OwnerNestingCtr;       (6)
    CPU_TS               TS;                        (7)
};
  • (1):互斥量的类型,用户无需理会,μC/OS能识别它是一个mutex。
  • (2):互斥量的名字,每个内核对象都被分配一个名。
  • (3):等待互斥量的任务列表。
  • (4):指向持有互斥量任务控制块的指针, 如果任务占用这个mutex,那么该变量OwnerTCBPtr会指向占用这个mutex的任务的OS_TCB。
  • (5):用于记录持有互斥量任务的优先级, 如果任务占用这个mutex,那么该变量OwnerOriginalPrio中存放着任务的原优先级,当占用mutex任务的优先级被提升时就会用到这个变量。
  • (6):表示互斥量是否可用,当该值为0的时候表示互斥量处于开锁状态, 互斥量可用。μC/OS允许任务递归调用同一个mutex多达256次,每递归调用一次mutex该值就会加一,但也需要释放相同次数才能真正释放掉这个mutex。
  • (7):mutex中的变量TS用于保存该mutex最后一次被释放的时间戳。 当mutex被释放,读取时基计数值并存放到该变量中。

注意:
用户代码不能直接访问这个结构体,必须通过μC/OS提供的API访问。

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

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

相关文章

SpringBoot第一个hello world项目

文章目录 前言一、Spring Boot是什么?二、使用步骤1. 创建项目2.书写测试 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了…

DRL-VWAP算法

摘要 在量化策略的交易端,为了更好的扩大策略的资金容量必须要考虑策略冲击陈本的降低。本文梳理了传统 VWAP 存在的诸多弊端,主要在于对于日内交易信息的缺失与忽略市场行情的影响。本文梳理了传统VWAP 算法存在的主要弊端,并改写了传统 VW…

20240409在全志H3平台的Nano Pi NEO CORE开发板运行的Ubuntu Core更新boot.img(eMMC启动)

20240409在全志H3平台的Nano Pi NEO CORE开发板运行的Ubuntu Core更新zImage内核 2024/4/9 9:21 一、生成zImage: 参考资料: http://wiki.friendlyelec.com/wiki/index.php/NanoPi_NEO_Core/zh#.E7.83.A7.E5.86.99.E5.88.B0eMMC NanoPi NEO Core/zh 6 FriendlyCore…

【leetcode面试经典150题】37. 矩阵置零(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…

大数据相关组件安装及使用

自学大数据相关组件 持续更新中。。。 一、linux安装docker 1、更新yum sudo yum update2、卸载docker旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine3、…

菜鸟IPO折戟背后:估值大幅下降,阿里巴巴为“分拆之痛”买单

撰稿|行星 来源|贝多财经 近日,阿里巴巴集团(下称“阿里巴巴”或“阿里”)发布公告,称其物流子公司菜鸟(同菜鸟物流、菜鸟网络)撤回在港交所的首次公开发行及上市申请,并计划收购菜鸟少数股东…

LeetCode31. 下一个排列(Java)

题目: 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列…

鸿蒙实战开发-如何实现查看系统相册、最近删除、收藏夹操作功能

介绍 本示例主要展示了相册相关的功能,使用ohos.file.photoAccessHelper 接口,实现了查看系统相册、创建用户相册、查看相册照片、用户相册文件添加和删除、以及预览图片、最近删除、收藏夹操作等功能; 效果预览 使用说明 主界面:查询显示…

一本想教会你滤波算法书

一本想教会你滤波算法书 从今天开始,这个博客系列会翻译一本 500 页左右的滤波算法的书,该书的原文连接我会放到后面的文中。翻译这本书不仅能继续我的英语学习(水平有限,有问题我留言我马上改!)而且可以跟…

如何合理利用Vue 3中的ref和reactive

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

大话设计模式——24.迭代器模式(Iterator Pattern)

简介 提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部实现。(Java中使用最多的设计模式之一) UML图 应用场景 Java的集合对象:Collection、List、Map、Set等都有迭代器Java ArrayList的迭代器源码 示例 简…

堆 和 优先级队列

目录 一、堆 二、优先级队列 1、初识优先级队列 2、实现一个优先级队列 3、PriorityQueue (1)实现了Comparable接口,重写了compareTo方法 (2)实现了Comparator接口,重写了compare方法 4、 Prio…

WordPress 图片压缩插件:Compress JPEG PNG images 使用方法

插件介绍 Compress JPEG & PNG images是一款非常好用的图片压缩插件:,非常值得大家安装使用;特别是图片类型网站。其实我们很多服务器磁盘空间是不在乎多那么几十 MB 大小的,但是压缩了图片能提升网站速度,节省宽带&#xff…

Linux网络名称空间之独立网络资源管理

Linux网络名称空间是一种强大的虚拟化技术🛠️,它允许用户创建隔离的网络环境🌐,每个环境拥有独立的网络资源和配置。这项技术对于云计算☁️、容器化应用📦和网络安全🔒等领域至关重要。本文将详细介绍在L…

python如何写入csv

在使用python对文件操作的过程中,你肯定碰到过对csv文件的操作,下面就python对csv文件的操作进行详述。 CSV(Comma-Separated Values)逗号分隔符,也就是每条记录中的值与值之间是用分号分隔的。 打开CSV文件并写入一…

第36篇:分频器<三>

Q:这一期我们介绍以计数器方式实现四分频的概念原理。 A:计数器分频有分频系数和占空比这两个参数。待分频时钟的频率为f1,分频后时钟的频率为f2,分频系数为Nf1/f2。 计数器分频电路通过对时钟信号计数来实现分频。根据分频系数可…

医院管理系统!(免费领取源码)

今天给大家分享一套基于SpringbootVue的医院管理系统源码,在实际项目中可以直接复用。(免费提供,文中自取) 系统运行图(设计报告和接口文档) 1、后台管理页面 2、排班管理页面 3、设计报告包含接口文档 源码免费领取方式 后台私信…

基于 SMM 汽车交易系统(源码+配套文档)

摘要 电子商务的兴起不仅仅是带来了更多的就业行业。同样也给我们的生活带来了丰富多彩的变化。多姿多彩的世界带来了美好的生活,行业的发展也是形形色色的离不开技术的发展。作为时代进步的发展方面,信息技术至始至终都是成就行业发展的重要秘密。不论…

如何彻底删除node和npm

如何彻底删除node和npm 前言: 最近做个项目把本地的node更新了,之前是v10.14.2更新至v16.14.0 ,想着把之前的项目起来下,执行npm install 结果启动不了,一直报npm版本不匹配需要更新本地库异常… 找了几天发现是npm 和…

【优选算法专栏】专题十三:队列+宽搜(一)

本专栏内容为:算法学习专栏,分为优选算法专栏,贪心算法专栏,动态规划专栏以及递归,搜索与回溯算法专栏四部分。 通过本专栏的深入学习,你可以了解并掌握算法。 💓博主csdn个人主页:小…