解析原理和实战Linux中如何正确地使用内存屏障

本文深入浅出地介绍了Linux系统中内存屏障的概念、作用和API,通过五个工程实战案例,阐述了如何正确使用内存屏障以确保多核处理器间的内存访问顺序,帮助读者理解和掌握这一关键的系统知识。
摘要由CSDN通过智能技术生成

圈里流传着一句话“珍爱生命,远离屏障”,这足以说明内存屏障是一个相当晦涩和难以准确把握的东西。使用过弱的屏障,会导致软件不稳定。使用过强的屏障,会引起性能问题。所以工程上,追求恰到好处、不偏不倚的屏障。本文力求用最浅显的语言,讲清楚内存屏障最晦涩的道理,本文也会给出五个工程案例,这些案例皆见于开源的代码,不涉及任何组织和个人未公开的技术。

一、引子

我国古代著名程序猿韩愈曾经写下一个名为《春雪》的函数:

新年都未有芳华,二月初惊见草芽。

白雪却嫌春色晚,故穿庭树作飞花。

这段代码讲述了一个关于memory reorder的故事,在计算机世界里面,冬天和春天并没有明确的界限,明明已经是春天了,但是还飘着冬天的雪。

下面我们看另外一段程序:

我们能确保c = 4吗?实际上,任何一个角度都确定不了。比如CPU0上面a = 3是“下雪”,flag = 1是“春天”,a=3看似在flag=1之前,实际可能由于memory reorder的原因发生在flag = 1之后,所以flag即便已经等于1,a也不一定等于3。

我们再退一万步讲,哪怕CPU0上面确实确保了春天不下雪,flag=1的时候a 100%就等于了3,那CPU1那边就万无一失了吗?答案也是否定的,因为,在CPU1上面,即便我们的代码是if(flag==1),接下来才做c=a+1,我们也不能确保a的load一定发生在flag==1之后。别忘了,CPU1会投机执行,比如碰到if(flag==1)这种条件,CPU可能直接忽略,不管三七二十一,还是可能先执行 load a, a+1的动作,然后反过来发现flag等于1,然后我认为我的投机是成功的;即便投机失败,CPU只需要保证load a, a+1的这些指令不retired就好。所以CPU1的load a, a+1完全可能发生在flag确切地等于1之前,因此即便CPU0保序了,CPU1仍然不能确保c=4。

我们看看CPU1在投机成功时候的行为逻辑和思想情感:

1. flag==1吗?

2. 不知道啊!我现在还没读出flag呢!

3. 管它呢,先假装flag==1吧,投机一把,执行load a, 把a+1看看

4.flag==1吗?哇,它真地等于1,太爽了,load a和a+1已经做完了。

如果投机失败了呢?

1. flag==1吗?

2. 不知道啊!我现在还没读出flag呢!

3. 管它呢,先假装flag==1吧,投机一把,执行load a, 把a+1看看

4. flag==1吗?Oh,shit,它不等于1,load a, a+1白做了.....

这就是弱序系统的典型特点。请问CPU为什么要这么“混乱”?这正是现代CPU为了保证高效执行厉害的地方,但是也引入软件使用上的复杂度。这种复杂度,类似于宋代著名程序媛李清照的函数《声声慢·寻寻觅觅》:“寻寻觅觅,冷冷清清,凄凄惨惨戚戚。乍暖还寒时候,最难将息。三杯两盏淡酒,怎敌他、晚来风急?雁过也,正伤心,却是旧时相识。满地黄花堆积,憔悴损,如今有谁堪摘?守着窗儿,独自怎生得黑。梧桐更兼细雨,到黄昏、点点滴滴。这次第,怎一个愁字了得!”请问李清照童鞋说的究竟是春天还是秋天还是春天呢?据说至今也没有人能够解密。仅凭“乍暖还寒”一定会觉得是初春,但是你再继续看到“雁过也”、“满地黄花堆积”,这显然又不是春天的景象。

罢了罢了,这一切都不重要了,重要的是,四季并不分明,四季没有明确的界限。这是我们要牢记的第一个point!

二、屏障

正是因为四季没有明确的界限,所以当我们希望看到明确的顺序的时候,我们希望引入一道屏障。让冬天跑不到春天,让春天跑不过去冬天。

典型的ARM64有这么几种屏障:

a. DMB:Data Memory Barrier

b. DSB:Data Synchronization Barrier

c. ISB:Instruction Synchronization Barrier

d. LDAR(Load-Acquire)/STLR(Store-Release)

我们随便打开ARM的手册,看一个DMB的定义:

The Data Memory Barrier (DMB) prevents the reordering of specified explicit data accesses across the barrier instruction. All explicit data load or store instructions, which are executed by the PE in program order before the DMB, are observed by all Observers within a specified Shareability domain before the data accesses after the DMB in program order.

码农的内心是崩溃的,人生已经这么悲催了,你为什么还要拿这样的绕口令来折磨我?什么叫“are observed by all Observers”?

下面我们给大家讲述2只狗狗出家门的故事:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值