ARM基础(5):内存屏障的必要性、内存类型和内存排序

news2025/2/1 1:56:13

在我们写代码的过程中,经常会发现在SDK中会出现__ISB()__DSB()等语句,这也做的目的是建立一个内存屏障,内存屏障可以由处理器内的硬件操作或内存屏障指令触发,它能够让CPU或编译器对屏障指令之前和之后的内存操作施加排序约束。

文章目录

  • 1 内存屏障的必要性
  • 2 内存类型
  • 3 内存排序
  • 4 内存排序的限制
  • 5 总结

1 内存屏障的必要性

在大多数的情况下,编译器可能会将一些数据缓存在寄存器中,或者对指令进行重排序以使程序运行地更快。这都可能造成我们数据传输的顺序与我们代码中预期的顺序不同。

比如,外设寄存器需要使用volatile声明以防止C编译器缓存数据,这样在每次访问寄存器时,处理器都将在总线上生成对应的传输时序。举个例子:我们需要定期从ADC寄存器中读出转换值,由于编译器不知道这个内存里的数据会改变,就可能就会对这个读取的过程进行优化,将读取的结果保存在寄存器中,而不是每次都从内存中读取。当然,如果将外设地址空间定义为cacheable,仍可能出现问题。

对于大多数系统来说,如果将所有外设寄存器声明为volatile,并将它们的内存空间定义为non-cacheable,那么一般不需要维护内存访问的顺序。然而,但流水线和cache本就是用来加速我们程序的执行速度的,特别是在一些GPU处理,数学运算的代码中,如果简单地关闭这些功能,处理器执行的效率会变低很多。举个例子,在Cortex-M处理器中,可以使用DMB(Data Memory Barrier)指令,以确保影响之前的内存访问已经完成后再执行下一个操作:
在这里插入图片描述
由于加了DMB指令,就保证了在指令N+3执行之前,所有的内存操作都已完成,即暂时停止指令流水线。

2 内存类型

在之前MPU的相关文章中,我有介绍我们一般将内存分为三种:Normal Memory(普通内存)、Device Memory(设备内存)和Strongly-ordered Memory(强有序内存)。

通常,用于程序代码和数据存储的内存是Normal Memory。但是有一些系统外设(I/O)通常不能按照普通内存来访问,以下是几个例子:

  • 中断控制器寄存器:用于处理中断的硬件组件。通过访问中断控制器寄存器,可以确认中断事件并改变控制器的状态。
  • 内存控制器配置寄存器:用于设置普通内存区域的时序和正确性。通过访问这些寄存器,可以配置内存控制器的行为,以确保内存的正确操作。
  • 内存映射外设:是指将外设的功能映射到内存地址空间的硬件组件。通过访问特定的内存位置,可以触发系统的一些副作用或执行外设的特定操作。

在这些情况下,由于外设的访问规则与Normal Memory不同,需要使用内存屏障来确保正确的内存访问顺序和同步。

在ARMv7(包括ARMv7-m)中,对系统外设的访问被定义为Device MemoryStrongly-ordered Memory访问,相比Normal Memory的访问来说,它们有更多限制:

  • 读和写都可能导致系统的异常行为
  • 访问不能重复,例如,从异常返回时
  • 必须维护访问的数量、顺序和大小。

Strongly-ordered Memory
内存映射的外设和I/O位置通常是强有序内存。在Cortex-M处理器中,System Control Space是强有序的,而SCS中包括NVICMPUSysTick定时器和调试组件。

对强有序内存的显式访问,以下规则适用:

  • 访问的大小与程序中指定的大小相符。比如,程序要求以字节为单位进行访问,处理器就必须按字节进行读取或写入,而不能超过或低于指定的大小。
  • 访问的次数与程序中指定的次数相符,即必须按照程序中指定的次数进行访问
    • 这个规则有例外情况,具体参考《ARMv7-M Architecture Reference Manual (ARM DDI 0403).》中的Exceptions in Load Multiple and Store Multiple operations

强有序内存中的地址范围不会被缓存,即MPU配置为shareable。这意味着内存系统必须维护数据的一致性,以允许多个处理器共享这些数据。对强有序内存的显式访问都必须符合内存排序要求中描述的排序要求,下面就来看看内存排序(Memory Ordering)。

3 内存排序

1、支持多种实现:ARMv7-M和ARMv6-M体系结构支持从低端微控制器到高端超标量SoC设计的广泛实现范围。为此,这些体系结构采用弱序内存模型。这个模型定义了三种内存类型,每种类型具有不同的属性和排序要求。

2、指令顺序和内存事务(对内存的读取和写入操作,包括指令读取和数据访问)顺序的不一致性:程序中指令的顺序不总是保证对应内存事务的顺序。这是因为:

  • 处理器可以重新排序一些内存访问以提高效率,前提是不影响指令序列的行为
  • 处理器可以拥有多个总线接口
  • 内存或内存映射的设备可以位于互联结构(用于连接各个处理器、内存和其他设备的通信通道或总线系统)的不同分支上
  • 某些内存访问是缓冲或推测性的(在等待某些操作完成的同时,预先执行可能的下一条指令)。

3、内存屏障的需要:在应用级别考虑内存排序模型时,关键是对于对普通内存的访问,在某些情况下需要屏障(barriers),以控制访问的顺序。

4、内存访问排序的限制:ARMv7-M和ARMv6-M定义了对内存访问排序的限制。这些限制取决于访问的内存属性。

内存访问排序要求中有两个概念:地址依赖性和控制依赖性
(1)地址依赖性(Address dependency)
地址依赖性发生在一个读操作返回的值被用于计算后续读或写操作的地址时。即使第一个读操作返回的值不改变第二个读或写操作的地址,仍然可能存在地址依赖性。这与处理器接口的实现方式有关。
(2)控制依赖性(Control dependency)
控制依赖性发生在一个读操作返回的数值用于决定一个条件码标志(condition code flags),而这个标志的值决定了后续读操作的地址时。

简而言之,地址依赖性关注的是读操作返回值对后续访问地址的影响,而控制依赖性关注的是读操作返回值对后续读操作地址的条件判断的影响。这些依赖关系在内存排序中需要考虑,以确保正确的数据访问顺序和正确的计算结果。

4 内存排序的限制

在并发系统中,多个访问操作可能会同时发生或交织在一起,而正确的访问顺序对于保证数据的一致性和正确性至关重要。通过要求访问在程序顺序中被全局观察到(访问在程序顺序中的先后顺序必须得到全局范围内所有观察者的一致确认。也就是说,无论是处理器、内存还是其他系统组件,它们必须能够准确地察觉到访问的顺序),系统能够确保每个观察者都能够按照正确的顺序感知到访问的发生,从而避免了由于并发导致的数据访问问题。

下表显示了两个显式访问(读或写操作)A1和A2之间的内存顺序,其中A1在程序中出现在A2之前。表中有两个符号:

  • <:在程序执行中,必须准确地按照顺序观察到访问行为,也就是说,A1必须在A2之前被全局观察到。
  • -:只要满足单处理器(这里不讨论多核)指令执行的顺序和行为与程序编写者的意图一致,遵守指令之间的依赖关系,那么访问可以以任意顺序在全局范围内被观察到。这强调了保持程序正确性的前提下,对访问顺序的灵活性。

注意:下表来自于ARMv6-M Architecture Reference ManualRevision D of the ARMv7-M Architecture Reference Manual。这与之前的ARMv7-M Architecture不同,Revision D版本删除了强顺序(Strongly-ordered)和普通(Normal)内存事务之间的排序要求。这是由于在最新的架构中,普通事务具有推测执行的能力,并且提供了更高性能实现的能力,可以在强顺序访问周围重新排序普通内存访问,除非通过屏障明确阻止这样做。


在这里插入图片描述
上表中标记为-的内存访问操作还有以下额外的限制:

  • 如果存在地址依赖性,那么两个内存访问会按照程序顺序进行观察
  • 如果只存在控制依赖性,则不需要按照顺序要求来观察两个读访问
  • 如果同时存在地址依赖性和控制依赖性,那么需要满足地址依赖性的排序要求
  • 如果一个读访问的返回值用于后续的写访问,那么这两个内存访问会按照程序顺序进行观察
  • 如果在程序的顺序执行中,某个内存位置不会被写入,那么观察者(如外设或第二个处理器)就不能观察到对该内存位置的写入操作或写入的值。即观察者只能观察到实际发生的写操作,而不能观察到未发生的写操作。

举个例子,A1和A2都是对一个Non-ShareableDevice Memory进行访问,这种情况下一定是要等A1的所有序列执行完毕后再执行A2,这个好理解,因为内存是不可共享的,也是不可缓存的。

再来来分析一下表中为-情况,举个例子:

A1: 处理器对外设A的Non-ShareableDevice Memory进行读取操作。
A2: 处理器对外设B的ShareableDevice Memory进行写入操作。

根据之前提到的原则,只要满足单处理器指令执行的顺序和行为与程序编写者的意图一致,保证处理器中指令之间的依赖关系,这两个访问操作可以以任意顺序在全局范围内被观察。这意味着观察者(例如外设或其他处理器)在观察到这两个访问操作时,它们的顺序是任意的。

5 总结

Cortex-M处理器相对于指令流程从不执行乱序内存访问,当然,未来不一定会有改变。因此,针对ARMv7-M的代码如果要在ARMv7-AR处理器(如Cortex-A9)上可移植,必须已经考虑了上面的排序模型。在Cortex-M处理器中,内存类型与内存映射相关联。定义了一些体系结构区域,并为每个区域定义了预定义的内存类型。当实现了MPU时,还可以通过编程来更改一些内存类型的定义。

在Cortex-M处理器上,可以使用MPU将SRAM定义为DeviceStrongly-ordered区域,但这会降低性能,并且无法阻止C编译器在生成的代码中重新排序数据传输。为了获得最佳效率,ARM建议将SRAM定义为Normal内存,并在内存排序重要的情况下使用内存屏障memory barriers

关于内存屏障和内存排序的知识十分复杂和抽象,但又十分重要,下一节我们将继续深入研究。

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

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

相关文章

cmake默认编译模式Debug or Release

CMAKE的编译选项 在阅读一些工程源码中&#xff0c;CMakeLists文件通常看到一下内容&#xff1a; set(CMAKE_CXX_FLAGS_DEBUG "-fPIC -O0 -g -Wall") set(CMAKE_CXX_FLAGS_RELEASE "-fPIC -O2 -g -Wall")那我们的编译时&#xff0c;用的到底是哪一个呢&a…

TypeScript 学习笔记(五):泛型

一、泛型是什么&#xff1f;有什么作用 软件工程中&#xff0c;我们不仅要创建一致的定义良好的API&#xff0c;同时也要考虑可重用性。 组件不仅能够支持当前的数据类型&#xff0c;同时也能支持未来的数据类型&#xff0c;这在创建大型系统时为你提供了十分灵活的功能。 在像…

【MySQL异常解决】Operation not allowed when innodb_forced_recovery > 0 的解决办法

Operation not allowed when innodb_forced_recovery > 0 的解决办法 一、背景描述二、解决方案三、拓展 一、背景描述 Spring Boot 项目&#xff0c;能正常启动&#xff0c;就是访问数据库时后台报错&#xff0c;Cause: java.sql.SQLException: Operation not allowed whe…

禁用 OPTIONS 请求

背景&#xff1a; 渗透测试结果为 不安全的HTTP方法 OPTIONS 描述 验证 curl -v -X OPTIONS http://localhost/xcall/token/refresh?_t1689589608解决方案&#xff08;2选1&#xff09;&#xff1a; 1.spring项目加上&#xff1a; import org.apache.tomcat.util.descript…

基于xinetd部署pwn题(百分百搭成并且可以nc靶场地址)

这种搭建方法需要你先装好docker&#xff0c;关于docker命令的安装这里就不过多介绍了&#xff0c;下面讲的是基于你已经安装好了docker&#xff0c;我们再使用xinetd在CTFd上部署pwn题目。 首先讲一下我自己搭建pwn题的一些经历&#xff0c;我最开始参考的是用socat命令来搭&a…

【DC-DC】APS54083 降压恒流驱动器大功率深度调光 舞台 RGB 汽车照明 台灯驱动芯片

产品描述 APS54083 是一款 PWM 工作模式,高效率、外围简单、外置功率 MOS 管&#xff0c;适用于 5-220V 输入高精度降压 LED 恒流驱动芯片。输出最大功率150W最大电流 6A。APS54083 可实现线性调光和 PWM 调光&#xff0c;线性调光脚有效电压范围 0.5-2.5V.PWM 调光频率范围 1…

MySQL第四章、表的增删查改(进阶)

目录 一、数据库约束 1.1约束类型 1.2NULL约束 1.3 UNIQUE&#xff1a;唯一约束 1.4 DEFAULT&#xff1a;默认值约束 1.5 PRIMARY KEY&#xff1a;主键约束 1.6 FOREIGN KEY&#xff1a;外键约束 1.7 CHECK约束&#xff08;了解&#xff09; 二、表的设计 2.1 一对一…

轻量级锁实现2——上锁、释放

瀚高数据库 目录 环境 文档用途 详细信息 环境 系统平台&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;14,13,12,11 文档用途 从底层理解轻量级锁的实现&#xff0c;从保护共享内存的角度理解轻量级锁的使用场景&#xff0c;包括上锁、等待、释放&…

SpringCloud(二)Eureka简介与依赖导入

一、Eureka Eureka能够自动注册并发现微服务&#xff0c;然后对服务的状态、信息进行集中管理&#xff0c;这样当我们需要获取其他服务的信息时&#xff0c;我们只需要向Eureka进行查询就可以了。 像这样的话&#xff0c;服务之间的强关联性就会被进一步削弱。 二、服务注册与…

图像处理之梯度及边缘检测算子

文章目录 一、sobel 算子二、Scharr算子三、Roberts算子四、拉普拉斯算子 梯度是一个量变化的速度&#xff0c;在数学中通常使用求导、求偏导获取梯度或者某一方向上的梯度。 在数字图像中梯度可以看为像素值分别在x,y方向上的变化速度&#xff0c;因为数字图像的离散型&#x…

vue3 如何将页面生成 pdf 导出

原文链接&#xff1a;vue3 如何将页面生成 pdf 导出 前言 最近工作中有需要将一些前端页面(如报表页面等)导出为pdf的需求&#xff0c;博主采用的是html2Canvas jspdf。 步骤 1.引入两个依赖 npm i html2canvas npm i jspdf点击 jsPDF GitHub、jsPDF 文档 查看关于jsPDF更多…

连续两个季度利润暴跌95%以上,三星回不去了

这两年&#xff0c;小编本人电脑的 CPU、显卡等核心硬件毫无升级欲望不愿折腾。 反倒是内存条、固态硬盘容量不知不觉翻了好几倍! 老实说&#xff0c;对大多数像咱这样的普通用户来说&#xff0c;CPU、显卡从两三年前的主流型号升级到现在的主流型号&#xff1b; 价格明显上涨…

求助:交流耦合放大电路(HPF)的阻抗匹配问题

1、同向的交流耦合放大电路 电路如下图所示&#xff0c;信号源是一个上升时间1ns&#xff0c;下降时间15ns的脉冲信号&#xff0c;经过传输线的时延为5ns&#xff0c;然后通过放大器的同向交流耦合放大&#xff0c;这里我们可以明确的直到&#xff0c;下图中的R25就是端接电阻…

JavaWeb——基于Spring Boot的图书数字化管理系统的设计与实现

课程设计总结 1 概述 1.1 项目开发背景 随着信息技术的快速发展&#xff0c;数字化管理已经成为各行各业提高效率和管理水平的重要手段。在图书管理领域&#xff0c;数字化管理系统可以有效地提高管理效率&#xff0c;提供更好的用户体验。本项目旨在开发一个基于Spring…

静态反射C++枚举名字的超简方案——C++闲得慌系列之(一)

C 有枚举&#xff0c;编译后其值就被转成整数了&#xff0c;有时程序会有输出枚举名字的需求&#xff0c;朴素的做法就是手工一个个写字符串&#xff08;名字&#xff09;&#xff0c;并实现匹配&#xff0c;比如&#xff1a; enum class Shape {rectangle, circular}; std::s…

再获信通院认可!华住&持安零信任项目获评零信任最佳方案奖!

2023年7月12日&#xff0c;在中国通信标准化协会算网融合产业及标准推进委员会&#xff08;CCSA TC621&#xff09;在京组织召开“2023算网融合产业发展峰会-零信任产业发展论坛”上&#xff0c;“2022零信任优秀案例”成果正式发布。 持安科技与华住集团共同完成的 “华住集团…

【SpringBoot】| Spring Boot 常见的底层注解剖析

目录 一&#xff1a;Spring Boot 常见的底层注解 1. 容器功能 1.1 组件添加 方法一&#xff1a;使用Configuration注解Bean注解 方法二&#xff1a;使用Configuration注解Import注解 方法三&#xff1a;使用Configuration注解Conditional注解 1.2 原生xml配置文件引入…

ITDR何以成为IAM的最佳搭档?

摘 要 ❖随着零信任方案的逐渐落地&#xff0c;身份成为企业的新边界。同时&#xff0c;身份基础设施成为了攻击焦点。 ❖最近的身份攻击变得更加巧妙和复杂&#xff0c;甚至可以绕过MFA。 ❖当前的IAM解决方案只能起到预防作用。 ❖企业更需要一个能够检测和响应身份威胁的…

Mysql 备份与还原

目录 一 数据库备份的重要性与分类 1.数据备份的重要性 2. 造成数据丢失的原因 3.从物理与逻辑的角度&#xff0c;备份分为 4.从数据库的备份策略角度&#xff0c;备份可分为 二、常见的备份方法 1.物理冷备 2.专用备份工具mydump或mysqlhotcopy 3.启用二进制日志进行增量…

上手vue2的学习笔记5之在vue2项目中调用elment-ui

前言 上手vue2的学习笔记4之搭建vue环境 参考链接&#xff1a;vue2.0项目引入element-ui 一、安装elment-ui 进入搭建的vue项目中 cd vue_bing_test 安装 element npm i element-ui二、引入elment-ui elment官方教程 将main.js改成如下内容&#xff1a; import Vue fro…