C 嵌入式系统设计模式 18:临界区模式

news2024/11/15 23:45:57

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

本系列描述我对书中内容的理解。本文章描述嵌入式并发和资源管理模式之四:临界区模式

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

临界区模式是任务协作中最简单的模式之一。其核心思想是在执行关键代码段时禁止任务切换,从而确保当前任务在执行这些敏感或不可中断的操作时不会被其他任务抢占。这种模式的使用场景通常涉及对共享资源的 独占访问 ,或者需要确保任务在特定时间内 无中断地执行 以保证系统的稳定性和正确性。

在临界区模式中,当一个任务进入临界区时,它会关闭或禁用任务切换机制,以防止其他任务打断当前任务的执行。这样做可以消除与资源共享相关的并发问题,如数据竞争和条件竞争,因为在这个时间段内只有当前任务能够访问相关资源。一旦任务完成了临界区内的操作,它会重新启用任务切换,允许其他任务继续执行。

摘要

在抢占式多任务环境中,可能存在某些时间段,其中任务不能被中断或抢占。临界区模式通过禁用任务切换或甚至禁用中断来处理这些关键的时间间隔。这确保了当前任务能够不受干扰地执行。一旦退出临界区,任务必须重新启用任务切换(或中断),否则系统将无法正常运行。

问题

在两种情况下,任务不能被中断或抢占:

  1. 资源访问的互斥性:当任务正在访问共享资源,如全局变量或硬件设备时,如果这些资源不能同时被多个任务安全地访问,那么中断或抢占当前任务可能会导致数据竞争或资源状态的不一致。
  2. 操作的原子性和顺序性:有些操作必须在无中断的情况下完成,以确保其原子性(即操作要么完全执行,要么完全不执行)或特定的执行顺序。

效果

临界区模式通过禁止任务切换或中断来确保活动任务在执行关键代码段时不会受到其他任务的干扰。这使得任务能够在没有潜在干扰的情况下完成其工作,从而保证了系统的稳定性和可靠性。

需要小心的是,在退出临界区后必须重新启用任务切换或中断。

此外,因为要关闭中断或者禁用任务切换,所以临界区模式可能会影响其他任务的执行时间。出于这个原因,临界区的持续时间通常很短。

由于在临界区期间禁用了所有任务切换,因此不存在不受控制的优先级反转问题。

嵌套使用临界区可能会带来问题(通常是软件编写缺陷造成的),我们在实现 进入临界区函数退出临界区函数 时要能支持嵌套。我来举一个不支持嵌套的例子来说明这种隐含缺陷。

CMSIS 也提供了使能中断和禁止中断的函数:

void __enable_irq(void);		//使能中断
void __disable_irq(void);		//禁止中断

查看反汇编,这两个函数分别对应着汇编代码:

CPSIE  I		;使能中断
CPSID  I		;禁止中断

这种禁止中断的方法是不支持嵌套使用的。比如一个这样的例子:

...				
__disable_irq();			//进入临界区
...
	//调用一个函数,在这个函数中也出现了开关中断操作(嵌套)
	__disable_irq();		//再次进入临界区,这一步无错误
	...
	__enable_irq();			//退出临界区,开中断,这步提前打开了中断
	//函数调用完毕
...
__enable_irq();				//期望在这里打开中断
...

注意看代码的第 7 行,这里退出临界区,开中断,从而提前打开了中断。根据代码逻辑,正确的打开中断应在代码的第 10 行。

RT-Thread 提供的使能全局中断或者禁止全局中断函数就具备嵌套使用的能力,具体例子可以参考我的博文 使能中断与禁止中断策略比较。

实现策略

这种模式通常通过使用调度器提供的服务来实现,例如OS_disable_task_switching()OS_enable_task_switching()(或类似的函数),或者通过引入汇编语言指令来在硬件级别禁用或启用中断处理。

无论使用哪种方法,都需要谨慎处理临界区的 进入退出 ,以确保不会意外地启用或禁用中断处理。此外,还需要注意临界区的长度和频率,以避免对系统性能产生过大的影响。如果临界区过长或频繁出现,可能会导致任务延迟、优先级反转或其他并发问题。

相关模式

这种模式仅在多个任务访问相同资源或服务,或者其他任务可能中断当前任务的时间关键处理时才适用。因此,它与 循环执行模式(Cyclic Executive Pattern)并不适用,但经常与 静态优先级模式(Static Priority Pattern)一起使用。

实例

见原书。






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

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

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

相关文章

【AIGC】OpenAI推出王炸级模型sora,颠覆AI视频行业(2024)

对于OpenAI推出的Sora模型,我们可以进一步探讨其可能的技术细节、潜在应用以及对AI视频行业的影响。 点击以下任一云产品链接,跳转后登录,自动享有所有云产品优惠权益: 经过笔者亲测,强烈推荐腾讯云轻量应用服务器作…

前端打包部署(黑马学习笔记)

我们的前端工程开发好了,但是我们需要发布,那么如何发布呢?主要分为2步: 1.前端工程打包 2.通过nginx服务器发布前端工程 前端工程打包 接下来我们先来对前端工程进行打包 我们直接通过VS Code的NPM脚本中提供的build按钮来完…

Http基础之http协议、无状态协议、状态码、http报文、跨域-cors

Http基础 HTTP基础HTTP协议请求方法持久连接管线化 无状态协议使用Cookie状态管理 状态码1XX2XX OK200 OK204 NO Content206 Content-Range 3XX 重定向301302304307 4XX400401403404 5XX500503 HTTP报文请求报文响应报文通用首部字段Cache-ControlConnectionDate请求首部字段Ac…

Python编程小案例—利用flask查询本机IP归属并输出网页图片

Python编程小案例—利用flask查询本机IP归属并输出网页图片 环境:Pycharm Mac OS 源码如下: from flask import Flask, render_template, requestapp Flask(__name__)app.route(/) def index():return render_template(IP查询.html)if __name__ __…

还在用Jenkins?快来试试这款简而轻的自动部署软件!

最近发现了一个比 Jenkins 使用更简单的项目构建和部署工具,完全可以满足个人以及一些小企业的需求,分享一下。 Jpom 是一款 Java 开发的简单轻量的低侵入式在线构建、自动部署、日常运维、项目监控软件。 日常开发中,Jpom 可以解决下面这些…

STM32 DMA入门指导

什么是DMA DMA,全称直接存储器访问(Direct Memory Access),是一种允许硬件子系统直接读写系统内存的技术,无需中央处理单元(CPU)的介入。下面是DMA的工作原理概述: 数据传输触发&am…

venv、pip、conda、anaconda、miniconda的区别和优缺点,和彻底清除python多余的环境

virtualenv(venv) 这是一个虚拟环境管理器,它可以让你每个项目甚至每个脚本配置一个自定义的Python解释器环境,这最大的好处是我可以不污染开发环境。​ pip pip 是 Python 最常用的包管理器,它能自动处理依赖 。 conda 如果说venv是虚拟…

5、DVWA代码审计(2)

一、csrf 1、csrf(low) 限制 复现 GET /vulnerabilities/csrf/?password_new123456&password_conf123456&ChangeChange HTTP/1.1 Host: ddd.com Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,…

探索数据宇宙:深入解析大数据分析与管理技术

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua,在这里我会分享我的知识和经验。&#x…

迪杰斯特拉算法的具体应用

fill与memset的区别介绍 例一 #include <iostream> #include <algorithm> using namespace std; const int maxn500; const int INF1000000000; bool isin[maxn]{false}; int G[maxn][maxn]; int path[maxn],rescue[maxn],num[maxn]; int weight[maxn]; int cityn…

Linux内存地址空间

目录 一、虚拟地址空间 1.虚拟地址空间的定义 2.虚拟地址空间的布局 二、内存壁垒 1.内存壁垒的定义​编辑 2.段错误 三、内存映射的建立与解除 &#xff08;1&#xff09;mmap &#xff08;2&#xff09;munmap &#xff08;3&#xff09;堆内存的分配和释放 1.sbrk …

一文掌握大模型提示词技巧:从战略到战术

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【c++】构造函数(下)——初始化列表

Hello,everybody!构造函数的内容比较多&#xff0c;语法还有些复杂。我分成了两篇文章进行讲解&#xff0c;大家在看过构造函数(上)后再来看这篇文章更容易理解哟&#xff01; 1.初始化列表的格式 类似这种格式&#xff0c;在初始化列表中第一行用冒号开头&#xff0c;剩下的用…

无线通信中AM,FM,PM与之相关的调制类型说明,例如F2D,F1W,F3E等

常见例子&#xff1a; 广播 A3E或A3E G 普通幅度调制用于低频和中频AM广播F8E&#xff0c;F8E H 用于VHF上的无线电传输的FM广播&#xff0c;以及模拟电视传输的音频分量。 由于通常使用用于立体声和RDS的导频音&#xff08;子载波&#xff09;&#xff0c;使用指示符“8”…

C++ 原子变量

概述 C中原子变量&#xff08;atomic&#xff09;是一种多线程编程同步机制&#xff0c;它能够确保对共享变量的操作在执行时不会被其他线程的操作干扰&#xff0c;atomic是提供一种生成原子操作数的一种机制&#xff0c;避免竞态条件(race condition)和死锁(deadlock)等问题。…

生成式AI与仿真

仿真模型是物理对象、系统或过程的虚拟表示&#xff0c;可预测其在不同场景中的行为和性能。 如今&#xff0c;仿真模型广泛应用于各行各业&#xff0c;以优化流程、为决策提供信息并创建数字孪生。 几十年来&#xff0c;仿真模型一直被用来对复杂的系统和过程进行建模。 这些…

Python 编辑工具 Jupyter notebook

Jupyter notebook Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算&#xff1a;开发、文档编写、运行代码和展示结果。——Jupyter Notebook官方介绍 官网&#xff1a;Project Jupyter | Home Jupyter Notebook 是一个开源的交互式计算环境&#…

selenium爬虫

方法选择和安装包 在动态网页并且登陆过程中不需要进行过于复杂的密码验证的时候使用selenium会非常的方便 安装准备过程也相对简单&#xff1a; 下载对应版本的chromedriver并且通过如下代码找到路径下载到python所在的目录&#xff1a; import sysprint(sys.executable) …

技巧 文本编辑器 B列每一行数据换行合并到A列中

一. 需求背景 ⏹A列是我们制作的日文版歌词&#xff0c;B列是中文版译文歌词 现在想让B列的每一行歌词&#xff0c;按下图箭头所示插入到A列的每一行后面 二. 通过文本编辑器的替换功能解决 将Excel中的A和B列的数据复制粘贴到文本编辑器中Excel中的列和列之前是通过Tab来分隔…

代码随想录算法训练营29期|day64 任务以及具体安排

第十章 单调栈part03 有了之前单调栈的铺垫&#xff0c;这道题目就不难了。 84.柱状图中最大的矩形class Solution {int largestRectangleArea(int[] heights) {Stack<Integer> st new Stack<Integer>();// 数组扩容&#xff0c;在头和尾各加入一个元素int [] ne…