linux内核中的内存屏障是如何使用的
内核源代码文档/memory-barriers.txt中有一个示例,如下所示:linux内核中的内存屏障是如何使用的,linux,memory,linux-kernel,memory-barriers,smp,Linux,Memory,Linux Kernel,Memory Barriers,Smp,内核源代码文档/memory-barriers.txt中有一个示例,如下所示: 我不明白,因为我们有写屏障,所以任何存储都必须在执行C=&B时生效,这意味着B将等于2。对于CPU 2,当它得到C的值时,B应该是2,也就是&B,为什么它认为B是7。我真的很困惑。从文件中题为“关于记忆障碍,什么是不可假设的?” 不能保证在 记忆屏障将通过完成记忆屏障来完成 指示屏障可以被认为是在该CPU的 适当类型的访问不能交叉的访问队列 及 无法保证CPU将看到正确的效果顺序 来自第二个CPU的访问,即使第二个C
我不明白,因为我们有写屏障,所以任何存储都必须在执行C=&B时生效,这意味着B将等于2。对于CPU 2,当它得到C的值时,B应该是2,也就是&B,为什么它认为B是7。我真的很困惑。从文件中题为“关于记忆障碍,什么是不可假设的?” 不能保证在 记忆屏障将通过完成记忆屏障来完成 指示屏障可以被认为是在该CPU的 适当类型的访问不能交叉的访问队列 及 无法保证CPU将看到正确的效果顺序 来自第二个CPU的访问,即使第二个CPU使用内存 屏障,除非第一个CPU也使用匹配的内存屏障(请参阅 关于“SMP势垒配对”的小节) 内存屏障所做的(当然是以非常简单的方式)是确保编译器和CPU硬件都不会对跨屏障的加载(或存储)操作进行任何巧妙的重新排序尝试,并且CPU能够正确地感知系统其他部分对内存所做的更改。当加载(或存储)具有额外的含义时,这是必要的,比如在访问我们要锁定的锁之前锁定它。在这种情况下,让编译器/CPU通过对访问进行重新排序来提高访问效率对程序的正确运行是有害的 阅读本文件时,我们需要记住两件事:
我希望这有帮助。我建议再次阅读memory-barriers.txt,特别是标题为“CPU缓存的影响”的部分。关键的缺失点是错误的假设,即对于序列:
LOAD C (gets &B)
LOAD *C (reads B)
第一次加载必须先于第二次加载。弱有序体系结构可以“好像”发生以下情况:
LOAD B (reads B)
LOAD C (reads &B)
if( C!=&B )
LOAD *C
else
Congratulate self on having already loaded *C
推测性的“加载B”可能会发生,例如,因为B与先前感兴趣的其他变量或硬件预取捕获它时位于同一缓存线上。很少有真正的机制用于重新排序依赖的加载。硬件(或编译器)需要一些理由才能猜测从
&B
加载可能是满足地址未知的加载的有用方法。价值预测是一种方法;一些模型。分支预测是另一种方法。是的,这是可能发生的,但其机制比简单的硬件预取要奇怪得多。
LOAD C (gets &B)
LOAD *C (reads B)
LOAD B (reads B)
LOAD C (reads &B)
if( C!=&B )
LOAD *C
else
Congratulate self on having already loaded *C