首页 > 系统相关 >内存管理——缓存一致性问题

内存管理——缓存一致性问题

时间:2022-09-04 11:33:25浏览次数:91  
标签:DMA 缓存 cache 内存 一致性 CPU

缓存一致性问题

问题1:多核CPU与cache的缓存一致性问题

多核CPU在访问内存时,每个核都有自己的cache,由于cache的写回机制,部分数据没有及时更新到内存,那么在不同线程访问同一个变量的时候就会出现不一致的情况

比如核心A访问address1,把address1的数据加载到A的cache中,核心B也访问address1并加载到B的cache中。如果核心A修改了这个数据,只会把cache中的数据修改并标记为dirty。在没有写回之前,核心B的cache中的同个数据还没改,当B去访问它时则会与A不一致。

要解决这一问题需要一种机制,来同步两个不同核心里面的缓存数据。要实现的这个机制的话,要保证做到下面这 2 点:

  1. 某个 CPU 核心里的 Cache 数据更新时,必须要传播到其他核心的 Cache,这个称为写传播(Write Propagation)
  2. 某个 CPU 核心里对数据的操作顺序,必须在其他核心看起来顺序是一样的,这个称为事务的串行化(Transaction Serialization)

事务串行化,也就是让不同核心看到的其他核心对于代码的执行顺序是一致的

要实现事务串行化,要做到 2 点:

  1. CPU 核心对于 Cache 中数据的操作,需要同步给其他 CPU 核心
  2. 要引入「锁」的概念,如果两个 CPU 核心里有相同数据的 Cache,那么对于这个 Cache 数据的更新,只有拿到了「锁」,才能进行对应的数据更新。

CPU用于保证缓存一致性,实现写传播和事务串行化,使用了基于总线嗅探 MESI 协议

MESI代表4种状态,协议用状态机机制降低了总线带宽压力。

MESI 状态
Modified 已修改
Exclusive 独占
Shared 共享
Invalidated 已失效

详情参考:https://xiaolincoding.com/os/1_hardware/cpu_mesi.html#mesi-协议

问题2:DMA与cache的缓存一致性问题

因为DMA是直接内存访问,对内存的访问不需要经过CPU,因此如果DMA修改了内存上的CPU访问过的数据,而CPU的cache中并不知道内存已经修改了,CPU读写内存的时候还是cache上的旧数据,造成缓存不一致问题。

也就是说,DMA和CPU可以异步地操作memory,解决访问冲突有两种方法,一种是禁止DMA目标地址范围内的cache功能。

一致性映射,代表函数:

void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);   //分配禁止C域和B域的内存给DMA
void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle); 

在 arm 平台上会禁止页表项中的 C (Cacheable) 域以及 B (Bufferable)域。C 代表是否使用高速缓冲存储器, 而 B 代表是否使用写缓冲区。

一般驱动使用多,申请一片uncached mem ,这样无需考虑data 一致性。代码流程:对kernel页管理的页面属性设置成uncache,在缺页异常填TLB时,该属性就会写到TLB的存储属性域中。保证了dma_alloc_coherent映射的地址空间是uncached的。

dma_alloc_coherent首先对分配到的缓冲区进行cache刷新,之后将该缓冲区的页表修改为uncached,以此来保证之后DMA与CPU操作该块数据的一致性。

另一种解决冲突的方法:

  • 在DMA拷贝前,进行一次CACHE CLEAN,将cache内容dirty回写,清除cache,保证在DMA传输时间内不会有回写动作
  • 在DMA拷贝完成之后,进行一次CACHE FLUSH,保证CPU访问目的地址时cache会重新构建,目的地址的值一定是从DDR上读取最新数据。

就能很大概率避免一致性的问题。

问题3:外设寄存器与cache的缓存一致性问题

CPU访问外设的数据寄存器和状态寄存器时,也是需要将寄存器的值映射到内存上进行读写,外设寄存器的值由硬件修改,也可以由CPU读写,因此外设和CPU对寄存器映射的内存访问也是异步的。CPU访问外设寄存器的时候会建立内存映射,然后将内存缓存到cache中,若此时外设寄存器的值发生了改变,CPU是不会发现这个变化而继续访问cache中的旧数据的。

因此cache或写缓冲的存在会带来外设寄存器的缓存一致性问题。

最好将外设寄存器配置成uncache,并不适用写缓冲,让CPU在每次访问时都去读外设端口寄存器。

通常,有cache的平台都有办法对某一段地址范围禁用Cache,一般是在页表中设置的,可以设定哪些页面允许Cache缓存,哪些页面不允许Cache缓存,MMU不仅要做地址转换和访问权限检查,也要和Cache协同工作。


好文推荐:CPU缓存一致性
DMA导致的CACHE一致性问题解决方案
ARM外设寄存器Cache一致性问题

标签:DMA,缓存,cache,内存,一致性,CPU
From: https://www.cnblogs.com/Ethan-Code/p/16652513.html

相关文章

  • 并发学习记录09:共享模型之内存
    Java内存模型JMM指的是Javamemorymodel,它定义了主存,工作内存等抽象概念,相当于做一个隔离层,将底层CPU寄存器,缓存,硬件内存,CPU指令优化提供的功能通过一个简单接口给使用......
  • Linux下查看系统中占用内存和CPU最多的进程
    Linux下查看系统中占用内存和CPU最多的进程前一段时间参加面试,被问到一个场景题:就比如说我们发现一台Linux的服务器,它的一些系统资源,比如说CPU内存都涨得比较厉害的。......
  • redis缓存恢复-2022新项目
    一、业务场景Web项目开发中,为了加快数据处理的的效率,大量的使用了各种缓存,缓存技术主要使用的是redis。导致出现的小小的问题是对redis缓存形成了一个比较强的依赖,并......
  • java 内存模型之 volatile 核心原理与应用
    1.happens-before规则https://blog.csdn.net/qq_39935047/article/details/1203847992.Juc12_Volatile的可见性、不保证可见性、有序性、使用、内存屏障四大指令StoreSt......
  • ENVI设置分块大小和缓存大小的方法
    设置ENVI分块和缓存大小,有助于提高处理效率。ENVI4.x和ENVIClassic的设置方法一样。ENVI5.5版本开始增加设置分块大小的选项。步骤1:添加权限由于会修改ENVI安装路径的......
  • pod中进行vi操作导致内存异常触发重启
    前天应用反馈说有个集群的访问异常抖动,于是查看了一下配置。发现pod异常重启了。于是怀疑是jmv异常,于是在pod中查看相关的日志。结果又重启了2次。于是对这二次进行分析......
  • MyBatis-缓存
    1.MyBatis缓存MyBatis中的缓存针对查询功能,可以将查询的数据进行缓存,再次查询相同数据时,不会从数据库中查询,直接从缓存中获取。分为一级缓存和二级缓存。2. MyBati......
  • 面试~jvm(JVM内存结构、类加载、双亲委派机制、对象分配,了解垃圾回收)
    一、JVM内存结构▷谈及内存结构各个部分的数据交互过程:还可以再谈及生命周期、数据共享;是否GC、是否OOM答:jvm内存结构包括程序计数器、虚拟机栈、本地方法栈、堆、方......
  • mysql查询数据库和数据表占用内存大小
    --查看所有数据库容量大小selecttable_schemaas'数据库',sum(table_rows)as'记录数',sum(truncate(data_length/1024/1024/1024,2))as'数据容量(GB)',sum(truncate......
  • 浏览器的缓存机制
    1、概述浏览器的缓存机制就是http缓存机制,是根据请求报文和响应报文的缓存标识来进行的。2、缓存过程浏览器缓存的关键:浏览器每次发起请求,都会先在浏览器缓存中查找该......