C 嵌入式系统设计模式 19:保护调用模式

news2024/12/23 7:00:25

本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。

本系列描述我对书中内容的理解。本文章描述嵌入式并发和资源管理模式之五:保护调用模式

保护调用模式 (Guarded Call Pattern) 是一种 任务协作模式。在软件设计中,任务协作模式是用于协调不同任务之间通讯和同步的策略。它旨在确保任务能够高效、有序地执行,并处理任务之间的依赖关系、优先级冲突和资源共享等问题。

保护调用模式用于 序列化 对某些服务的访问。当多个调用者同时调用这些服务时,可能会以某种方式产生干扰。所以不能直接调用这些服务,而是通过提供锁定机制来序列化访问,防止其他线程在锁定期间调用这些服务。具有这套保护机制的调用服务,称为 保护调用模式。简而言之,此模式通过 来确保同时只有一个线程能够使用特定资源或服务,从而避免潜在的并发问题

摘要

在抢占式多任务环境中,保护调用模式 使用 信号量 来保护一组相关的函数。这些函数组合起来提供某种 服务 。这样就能防止多个客户端同时访问这些服务,这个过程被称为 互斥

然而,如果不与其它模式混合使用,这种模式可能会导致不受控制的优先级翻转。

问题

该模式解决的是线程之间的同步或数据交换问题。在这种情况下,可能无法等待 异步会合,可以更及时地进行 同步会合 ,但必须小心进行,以避免数据损坏和计算错误。

异步同步 :异步是一种处理并发操作的方法,允许程序在等待某些操作完成(如 I/O 操作)的同时,继续执行其他任务。这种方法与同步操作相对,同步操作会阻塞程序执行,直到等待的操作完成为止。比如,用 队列 来实现异步,用函数调用来实现同步。

会合 :即同步点,任务的动作序列中的一个特定动作,任务会在此等待,直到其他任务也达到相应的同步点。

在异步环境中,线程之间的会合可能是不确定的,因此等待异步会合可能不是一种可靠或高效的方法。因此书中说 保护调用模式 可能不适用于异步会合。

模式结构

模式结构如下图所示:

在这里插入图片描述
在这种情况下,多个 抢占式任务(PreemptiveTasks)通过资源模块提供函数访问 受保护资源(GuardedResource)。在这些函数内部,会调用 锁定释放 资源的操作。调度器支持阻塞,当任务调用已被锁定的信号量时,将其放置在阻塞队列中,并在该信号量释放时解除其阻塞。调度器必须将信号量的 lock() 函数实现为 临界区,以消除竞态条件的可能性。

模式详情

受保护的资源

受保护的资源 是一个共享资源,它使用互斥信号量来保护自己提供的函数,强制调用者互斥访问。在它提供的函数内部,当访问之前,会调用关联的 信号量 实例的 lock() 函数。如果信号量处于未锁定状态,则该资源被锁定;如果资源已处于锁定状态,则信号量会通知 静态优先级调度器 阻塞当前正在运行的任务。重要的是,特定资源实例的相关函数必须共享同一个信号量类的实例。这确保了它们作为一个单元受到保护,防止多个 抢占式任务 同时访问。

特定资源实例的相关函数必须共享同一个信号量类的实例:这是确保资源正确保护的关键。如果每个函数都有自己的信号量实例,那么它们就无法有效地协调对共享资源的访问。相反,通过共享同一个信号量实例,它们可以确保在任何时候只有一个任务能够访问该资源。

抢占式任务

抢占式任务 表示一个通过抢占式多任务调度器运行的任务。它通过调用 受保护的资源 的函数来访问该资源,而这些函数又受到信号量的保护。这样确保了抢占式任务在访问受保护的资源时不会受到其他任务的干扰,从而保证了数据的一致性和系统的稳定性。

信号量

这里 信号量 使用的是互斥信号量,用于 序列化受保护的资源 的访问。受保护的资源的受保护函数在被调用时会调用信号量的 lock() 函数,并在服务完成后调用 release() 函数。当关联的信号量被锁定时,尝试调用服务的其他客户端线程将被阻塞,直到信号量解锁。这个元素通常由 RTOS(实时操作系统)提供。

效果

保护调用模式提供了对资源的及时访问,并通过锁定机制防止了多个同时访问,这些同时访问可能会导致数据损坏或系统错误行为。当资源未被锁定时,访问可以立即进行,没有任何延迟,从而保证了系统的实时性。如果资源被锁定,调用者必须等待锁释放,这可能导致调用者被阻塞一段时间。然而,如果不当地使用这种模式,可能会导致不受控制的优先级反转。

实现策略

实现 保护调用模式 的关键部分在于 互斥量 的实现。通常,RTOS 会提供这个信号量(互斥量是信号量的一种)。一般会有以下操作:

  1. 创建一个信号量
  2. 销毁一个信号量
  3. 锁定信号量
  4. 释放信号量

相关模式

保护调用模式在抢占式多任务环境中使用,比如使用 静态优先级调度器 的环境。与 临界区模式 相比,它不会干扰不需要访问资源的更高优先级任务的执行;与 队列模式 相比,它响应更迅速,因为当资源有效时,操作系统会解除等待资源的任务。

这个模式有一类非常重要的变体,它使用 优先级继承 的概念来解决 不受控制的优先级反转 的问题。基本思想是,每个资源都有一个额外的属性(变量),称为优先级上限(priority ceiling),它等于能够访问该资源的最高优先级任务的优先级。

注:实际上,目前主流的 RTOS 提供的互斥量都是具有优先级继承的。

为什么要使用具有优先级继承的互斥量来实现保护调用模式?

不使用具有优先级继承的互斥量来实现保护调用模式,称为 原始的保护调用模式 ,它存在一个根本的问题是:会产生不受控制的优先级反转 问题。即,不需要该资源的中等优先级任务可以抢占当前拥有被阻塞的高优先级任务所需资源的低优先级任务。这样的中等优先级任务可能有任意多个,导致高优先级任务被连锁阻塞。这句话可能很绕,我来举一个例子:

如下图所示,任务 A 和任务 Z 会使用资源 R ,而任务 X 和任务 Y 并不直接使用资源 R,但它们会影响任务 A 和任务 Z 的执行。
在这里插入图片描述
最坏情况如下所示:

  1. 任务 Z 首先运行并锁定了资源 R。
  2. 任务 A 开始运行,任务 A 优先级更高,它立即抢占任务 Z。任务 A 运行到需要访问资源 R 的时候,因得不到资源 R 而被阻塞。
  3. 此时,任务 Z 继续运行
  4. 但紧接着任务 Y 开始运行,由于任务 Y 优先级高于任务 Z,因此它立即抢占任务 Z。
  5. 在任务 Y 运行期间,任务 X 变得可以运行,并且由于任务 X 的优先级高于任务 Y,因此它立即抢占任务 Y。

这样,任务 A 被三个低优先级的任务(Z、Y 和 X)所阻塞,无法访问所需的资源 R。

由于任务 Y 和任务 X 的执行,最坏情况下任务 A 需要 190 ms ( 任务 Z 锁定资源 10 ms + 任务 Y 执行时间 100 ms + 任务 X 执行时间 80 ms)才能获得资源 R 。这导致了任务 A 错过其截止时间,因为它无法在 50ms 的周期内完成任务。这种现象称为 不受控制的优先级反转 ,是一个严重的问题,因为它可能导致高优先级任务无法及时完成,从而影响系统的实时性能和可靠性。

还是上面图中所示的情况,我们再来看一下使用 优先级继承 机制后,带来的变化:

  1. 任务 Z 首先运行并锁定了资源 R。
  2. 任务 A 开始运行,任务 A 优先级更高,它立即抢占任务 Z。任务 A 运行到需要访问资源 R 的时候,因得不到资源 R 而被阻塞。此时,任务 Z 的优先级会被 提升 到任务 A 的优先级,即优先级为 1
  3. 此时,任务 Z 继续运行
  4. 紧接着,任务 Y 处于就绪状态,但是由于任务 Z 的优先级已经提升到和任务 A 相同的优先级,因此任务 Y 无法抢占任务 Z 的执行
  5. 相同的原因,就绪状态的任务 X 同样无法抢占任务 Z 的执行
  6. 任务 Z 完成了对资源 R 的使用并解锁了它。在优先级继承机制下,当任务Z释放资源R时,它的优先级将从提升的优先级(=1)降低回其原始优先级(=99)。
  7. 任务 A 会立即解除阻塞,并获得资源 R 的使用权。任务 A 可以在截止时间之前完成任务。

通过这个简单的例子,我们可以看到优先级继承如何防止了不受控制的优先级反转的问题,这是普通的计数信号量所无法避免的。

实例

见原书。






读后有收获,资助博主养娃 - 千金难买知识,但可以买好多奶粉 (〃‘▽’〃)
千金难买知识,但可以买好多奶粉

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

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

相关文章

Linux服务器搭建超简易跳板机连接阿里云服务器

简介 想要规范内部连接阿里云云服务器的方式,但是最近懒病犯了,先搞一个简易式的跳板机过渡一下,顺便在出一个教程,其他以后再说! 配置方法 创建密钥 登录阿里云,找到云服务器ECS控制台,点击…

Unity 脚本-生命周期常用函数

在Unity中,万物皆是由组件构成的。 右键创建C#脚本,拖动脚本到某物体的组件列表。 生命周期相关函数 using System.Collections; using System.Collections.Generic; using UnityEngine;// 必须要继承 MonoBehaviour 才是一个组件 // 类名…

分付在哪些商户可以使用消费,微信分付怎么提取出来到余额上面来?

分付是一款信用支付产品,用户可以使用分付进行线上线下的消费支付。下面是使用分付的一些方法: - 开通分付:在微信中搜索并开通分付服务,按照提示完成实名认证和绑定银行卡等操作。 - 线上支付:在支持分付的线上商户…

《手把手教你》系列技巧篇(十五)-java+ selenium自动化测试-元素定位大法之By xpath中卷(详细教程)

1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath。xpath 的定位方法, 非常强大。 使用这种方法几乎可以定位到页面上的任意元素。 2.什么是xpath? xpath 是XML Path的…

六、矩阵问题

73、矩阵置零(中等) 题目描述 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1: 输入:matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a…

OpenAI工作环境曝光:高薪背后的996;Quora的转变:由知识宝库至信息垃圾场

🦉 AI新闻 🚀 OpenAI工作环境曝光:高薪背后的996 摘要:近日,多位OpenAI匿名员工在求职网站Glassdoor上披露了公司的工作环境和公司文化,包括高薪水和优厚的福利待遇,但同时伴随着996的加班文化…

pdf编辑软件哪个好用?5款PDF编辑器分享

pdf编辑软件哪个好用?PDF编辑软件在现代办公和学术研究中发挥着举足轻重的作用,它们不仅具备基础的编辑和修改功能,还能够支持多种注释工具,帮助我们高效地管理和整理PDF文件。无论是需要调整文档布局、添加文本或图像&#xff0c…

程序员的金三银四求职宝典:如何在关键时期脱颖而出?

个人主页:17_Kevin-CSDN博客 随着春天的脚步渐近,程序员们的求职热潮也随之而来。在这个被称为“金三银四”的招聘季,如何从众多求职者中脱颖而出,成为了许多程序员关注的焦点。本文将为你提供一份全面的求职宝典,助你…

现货大宗软件数据处理模块源码

现货大宗软件数据处理模块源码:揭秘背后的技术魅力 在当今的大数据时代,无论是金融、贸易还是其他领域,数据处理都显得尤为重要。特别是对于现货大宗交易来说,数据处理不仅关乎交易的速度与效率,更直接影响到交易的成…

基于嵌入式的车载导航定位系统设计

一、前言 1.1 项目介绍 【1】项目背景 随着汽车工业的飞速发展和智能化技术的不断突破,车载导航系统作为现代汽车不可或缺的一部分,在人们的日常生活中扮演着越来越重要的角色。它不仅能够提供精确的路线导航,还能提供丰富的地理信息和娱乐…

Java:JVM基础

文章目录 参考JVM内存区域程序计数器虚拟机栈本地方法栈堆方法区符号引用与直接引用运行时常量池字符串常量池直接内存 参考 JavaGuide JVM内存区域 程序计数器 程序计数器是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器,各线程…

mprpc分布式RPC网络通信框架

mprpc 项目介绍 该项目是一个基于muduo、Protobuf和Zookeeper实现的轻量级分布式RPC网络通信框架。 可以把任何单体架构系统的本地方法调用,重构成基于TCP网络通信的RPC远程方法调用,实现同一台机器的不同进程之间的服务调用,或者不同机器…

[ai笔记14] 周鸿祎的ai公开课笔记1

欢迎来到文思源想的ai空间,这是技术老兵重学ai以及成长思考的第14篇分享! 本周二月的最后一周,并不是闲下来了,反而是开始进行一些更多的深入实践,关于gpt的主体架构、关于prompt,同时也看了不少书和直播&…

【Linux】基本指令(中)

🦄个人主页:修修修也 🎏所属专栏:Linux ⚙️操作环境:Xshell (操作系统:CentOS 7.9 64位) 目录 man指令 cp指令 mv指令 cat指令 more指令 less指令 head指令 …

Go语言中的时间控制:定时器技术详细指南

Go语言中的时间控制:定时器技术详细指南 引言定时器基础创建和使用time.Timer使用time.Ticker实现周期性任务定时器的内部机制小结 使用time.Timer实现简单的定时任务创建和启动定时器停止和重置定时器定时器的实际应用小结 利用time.Ticker处理重复的定时任务创建和…

PHP【swoole】

前言 Swoole官方文档:Swoole 文档 Swoole 使 PHP 开发人员可以编写高性能高并发的 TCP、UDP、Unix Socket、HTTP、 WebSocket 等服务,让 PHP 不再局限于 Web 领域。Swoole4 协程的成熟将 PHP 带入了前所未有的时期, 为性能的提升提供了独一无…

[晓理紫]CCF系列会议截稿时间订阅

CCF系列会议截稿时间订阅 关注{晓理紫|小李子},每日更新最新CCF系列会议信息,如感兴趣,请转发给有需要的同学,谢谢支持!! 如果你感觉对你有所帮助,请关注我,每日准时为你推送最新CCF…

学习使用paddle来构造hrnet网络模型

1、首先阅读了hrnet的网络结构分析,了解到了网络构造如下: 参考博文姿态估计之2D人体姿态估计 - (HRNet)Deep High-Resolution Representation Learning for Human Pose Estimation(多家综合)-CSDN博客 最…

3、Redis Cluster集群运维与核心原理剖析

Redis集群方案比较 哨兵模式 在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可用性…

用numpy搭建自己的神经网络

搭建之前的基础与思考 构建模型的基本思想: 构建深度学习的过程:产生idea,将idea转化成code,最后进行experiment,之后根据结果修改idea,继续idea–>code–>experiment的循环,直到最终训练…