主要参考书籍:《CSAPP》、《图解操作系统》
上回学到了写传播
在解决这个缓存一致性的问题,其实我们只需要做到写传播和事务串行化
写传播就是指一个核心的cache发生了数据变更,必须传播到其他的核心当中去。
不过还存在一个问题,不同核心接收到传播的数据变更顺序可能不一样。我们必须保证不同
核心接收到的数据变更顺序是一样的。--我们称之为事务串行化
如何实现写传播与事务串行化
总线嗅探
Bus Snooping 每个核心都时时刻刻监听着总线上的广播条件 , 每次自己核心发生数据变更的时候,就发出广播事件
然后监听的核心检查变动的数据在自己的cache里面存不存在,如果也存在这个数据的话,就也更新自己的数据内容。
这样的话就能够实现写传播,虽然会给总线带来不少的负荷(但这是不可避免的)
可是还是没实现事务串行化,于是就
MESI协议
MESI协议是已修改(Modified)、独占(Exclusive)、共享(Shared)、失效的(Invalid)四个状态的英文首字母缩写组成的协议。
四个状态组成了有限状态机,四个状态的变化来自于本地的CPU cache请求或者是总线上其他核心CPU cache的请求。
主要能够理解状态机的运转就嗯呢该理解基于总线嗅探的MESI协议
能够深度、完整地描述出这两张图的过程 MESI协议基本就过关了。
虽然前面有提到用锁来解决事务串行化的问题,但在MESI协议中又没有提到关于锁的内容。
有关CPU读写数据的问题
虽然标题是关于CPU是如何读写数据的,但在之前其实有很多内容已经重复和讲解了,其实讲解的内容更多地是针对一些
CPU读写机制造成的问题。比如说下面这个问题:
伪共享
多个线程不断交替修改同一个cache line上的不同变量时导致的CPU cache存储数据失效的问题
如何避免伪共享
在Linux中有些时候多核系统会通过用空间换时间的思想去避免这个问题的发生
通过宏定义的字节对齐将不同变量放在不同的cache line 中
而CPU如何读写数据从前面几节我们也能略知一二了:
CPU核心通过内存地址(包含有很多信息)先从缓存开始读数据,读到了就结束(缓存命中),否则一路向下,沿着存储金字塔的结构一路走到存储的最底层【也未必就是最底层】(内存)。过程中涉及一些需要解决的问题:写数据、缓存保持一致...
有关CPU线程、进程的问题
其实很奇怪 在第一章为了能够理解程序在CPU中是如何运行的,需要用很多后面的知识(陌生,还没学)去理解
- 线程、进程的基础在图解系统的第四章,因此我们也直接跳到第四章一并解决了这些问题。(后续搞吧)
当然我们最终是为了理解程序在CPU中是如何运行的。
因为在系统运作的过程中有很多的线程和进程在运行,于是我们需要了解系统是如何选择哪个线程、进程去运行
所以线程、进程是什么暂时不用知道。