伪共享之CPU缓存
前言
分享一下伪共享。一共分为两篇文章。第一篇是基础篇,主要讲CPU缓存。废话不多说直接奔主题。
CPU缓存
CPU缓存的定义是位于CPU与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多
。CPU 和主内存之间有好几层缓存,因为即使直接访问主内存也是非常慢的。
按照数据读取顺序和与CPU结合的紧密程度,CPU缓存可以分为一级缓存(L1),二级缓存(L2),部分高端 CPU还具有三级缓存(L3)。每一级缓存中所储存的全部数据都是下一级缓存的一部分,越靠近CPU的缓存越快也越小。所以L1缓存很小但很快,并且紧靠着在使用它的CPU内核。L2大一些,也慢一些,并且仍然只能被一个单独的CPU核使用。L3在现代多核机器中更普遍,仍然更大,更慢,并且被单个插槽上的所有CPU核共享。最后,你拥有一块主存,由全部插槽上的所有CPU核共享。拥有三级缓存的的CPU,到三级缓存时能够达到95%的命中率,只有不到5%的数据需要从内存中查询。
看下图:[<img src=“https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/5/21/16380aa34953407b~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.image)](https://link.juejin.cn/?target=http%3A%2F%2Fwyj.shiwuliang.com%2Fimages%2F15266967502066.jpg “http://wyj.shiwuliang.com/images/15266967502066.jpg”” style=“margin: auto” />
MESI协议和RFO请求
从上一节中我们知道,每个核都有自己私有的L1、L2缓存。那么多线程编程时, 另外一个核的线程想要访问当前核内L1、L2缓存行的数据, 该怎么办呢?
有人说可以通过第2个核直接访问第1个核的缓存行,这是当然是可行的,但这种方法不够快。跨核访问需要通过Memory Controller(内存控制器,是计算机系统内部控制内存并且通过内存控制器使内存与CPU之间交换数据的重要组成部分),典型的情况是第2个核经常访问第1个核的这条数据,那么每次都有跨核的消耗.。更糟的情况是,有可能第2个核与第1个核不在一个插槽内,况且Memory Controller的总线带宽是有限的,扛不住这么多数据传输。所以,CPU设计者们更偏向于另一种办法:如果第2个核需要这份数据,由第1个核直接把数据内容发过去,数据只需要传一次
。
MESI就是解决这种状况的协议,现在主流的处理器都是用它来保证缓存的相干性和内存的相干性。M、E、S 和 I 代表使用 MESI 协议时缓存行所处的四个状态:
- M(修改,Modified):本地处理器已经修改缓存行,即是脏行,它的内容与内存中的内容不一样,并且此 cache 只有本地一个拷贝(专有)。
- E(专有,Exclusive):缓存行内容和内存中的一样,而且其它处理器都没有这行数据。
- S(共享,Shared):缓存行内容和内存中的一样, 有可能其它处理器也存在此缓存行的拷贝。
- I(无效,Invalid):缓存行失效, 不能使用。
语言总是苍白的,看图。
E状态:
[<img src=“https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/5/21/16380aa349a70edf~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.image)](https://link.juejin.cn/?target=http%3A%2F%2Fwyj.shiwuliang.com%2Fimages%2F15266991199388.jpg “http://wyj.shiwuliang.com/images/15266991199388.jpg”” style=“margin: auto” />
这种状态下,只有CORE0独享x变量,它的cache line状态为E。
S状态:
[<img src=“https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/5/21/16380aa34993212a~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.image)](https://link.juejin.cn/?target=http%3A%2F%2Fwyj.shiwuliang.com%2Fimages%2F15266992615449.jpg “http://wyj.shiwuliang.com/images/15266992615449.jpg”” style=“margin: auto” />
3个CORE都访问变量x,它们对应的cache line为S状态。
M状态和I状态:[<img src=“https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/5/21/16380aa349d932d3~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.image)](https://link.juejin.cn/?target=http%3A%2F%2Fwyj.shiwuliang.com%2Fimages%2F15266993216408.jpg “http://wyj.shiwuliang.com/images/15266993216408.jpg”” style=“margin: auto” />
CORE0修改了x的值之后,这个cache line变成了M状态,其他CORE对应的cache line变成了I状态。
在MESI协议中,每个cache的Cache控制器不仅知道自己的读写操作,而且也监听其它Cache的读写操作。每个cache line所处的状态根据本核和其它核的读写操作在4个状态间进行迁移。
RFO请求当是CORE0得到CORE1的数据后,不是为了读,而是为了写。也算是本地写,只是CORE1也拥有这份数据的拷贝,这该怎么办呢?CORE0将发出一个RFO(Request For Owner) 请求,它需要拥有这行数据的权限,其它处理器的相应缓存行设为I,除了它自已,谁不能动这行数据。这保证了数据的安全,同时处理RFO请求以及设置I的过程将给写操作带来很大的性能消耗。
缓存行及工作原理
之前一直说缓存行,最后说一下这个缓存行的工作原理。
缓存系统中是以缓存行(cache line)为单位存储的。缓存行通常是 64 字节(其他长度的如32字节等不考虑),并且它有效地引用主内存中的一块地址。
cache line:
状态 | 地址 | 数据 |
---|---|---|
- 状态:MESI协议中的一种。
- 地址:cache line中映射的内存地址。
- 数据:从内存中读取的数据。
CPU访问主内存, 都是通过cache间接访问主存,每次需要访问主存时,遍历一遍全部cache line,查找主存的地址是否在某个cache line中,如果在,先判断数据是否有效(根据状态),有效则直接用。如果不在或者数据无效,把主存的内存copy到cache line中, 再从cache line中读取。
To be continued
至此,cpu缓存策略和基本工作原理结束了。下一篇会讲解伪共享,以及如何避免伪共享。## 最后
从时代发展的角度看,网络安全的知识是学不完的,而且以后要学的会更多,同学们要摆正心态,既然选择入门网络安全,就不能仅仅只是入门程度而已,能力越强机会才越多。
因为入门学习阶段知识点比较杂,所以我讲得比较笼统,大家如果有不懂的地方可以找我咨询,我保证知无不言言无不尽,需要相关资料也可以找我要,我的网盘里一大堆资料都在吃灰呢。
干货主要有:
①1000+CTF历届题库(主流和经典的应该都有了)
②CTF技术文档(最全中文版)
③项目源码(四五十个有趣且经典的练手项目及源码)
④ CTF大赛、web安全、渗透测试方面的视频(适合小白学习)
⑤ 网络安全学习路线图(告别不入流的学习)
⑥ CTF/渗透测试工具镜像文件大全
⑦ 2023密码学/隐身术/PWN技术手册大全
如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!
扫码领取
