linux内存屏障

  • why? 为什么要有内存屏障,内存屏障主要解决什么问题

  • What? 内存屏障都有哪些

  • How? 内存屏障如何使用

本篇文章主要解决前两个问题

一、为什么要有内存屏障

我们都知道计算机运算任务需要CPU和内存相互配合共同完成,其中CPU负责逻辑计算,内存负责数据存储。CPU要与内存进行交互,如读取运算数据、存储运算结果等。

由于内存和CPU的计算速度有几个数量级的差距,为了提高CPU的利用率,现代处理器结构都加入了一层读写速度尽可能接近CPU运算速度的高速缓存来作为内存与CPU之间的缓冲。

将运算需要使用的数据复制到缓存中,让CPU运算可以快速进行,计算结束后再将计算结果从缓存同步到主内存中,这样处理器就无须等待缓慢的内存读写了。就像下面这样。

每个CPU都会有自己的缓存(有的甚至L1,L2,L3),缓存的目的就是为了提高性能,避免每次都要向内存取,但是这样的弊端也很明显:不能实时的和内存发生信息交换,会使得不同CPU执行的不同线程对同一个变量的缓存值不同 。

总结来说,现在大多数现代计算机为了提高性能而采取乱序执行,乱序执行可能会导致程序运行不符合我们预期,这使得内存屏障成为必须。

linux内存屏障_第1张图片

二、乱序访问

乱序访问分为两类,一类是编译时内存乱序访问,一类是运行时乱序访问。

2.1 编译时内存乱序访问

编译器对代码做出优化时,可能改变实际执行指令的顺序(例如g++下O2或者O3都会改变实际执行指令的顺序),看一个例子

int x, y, r;
void f()
{
    x = r;
    y = 1;
}

首先直接编译次源文件:g++ -S test.cpp。我们得到相关的汇编代码如下:

movl    r(%rip), %eax
movl    %eax, x(%rip)
movl    $1, y(%rip)

这里我们可以看到,x = r和y = 1并没有乱序执行。现使用优化选项O2(或O3)编译上面的代码(g++ -O2 –S test.cpp),生成汇编代码如下:

movl    r(%rip), %eax
movl    $1, y(%rip)
mov

你可能感兴趣的:(Linux,内核,linux内存屏障,smb,rmb)