虽然实际驱动中不常用,但是阅读内核比较深层的代码经常会遇到.为什么存在内存屏障呢?先看一下下面的场景:
编译器和处理器为了提高效率,可能对读和写操作重新进行了排序,例如:
在某些处理器上,以下代码:
A = 1;
B = 2;
有可能在A中存放新值之前就在B中存放新值.
但是,我们在操作内存或者和硬件交互时,常常需要确保一个给定的顺序.所有可能重新排序和写的处理器提供了机器指令来确保顺序要求,同样也可以提示编译器不要对给定点周围的指令序列进行重新排序.这些确保顺序的指令叫做"屏障".
内存屏障的存在意义就是为了解决编译器和处理器对代码的顺序访问问题.
内核中用于内存屏障的API有:
rmb():提供"读"内存屏障,确保跨越rmb()的载入动作不会发生重排序.就是说,rmb()之前的载入操作不会被重新排在rmb()之后去;
wmb():
方法提供了"写"内存屏障,功能和rmb()函数类似.区别仅仅是针对存储而非载入--确保跨越屏障的存储不发生排序;
mb():
提供了读屏障也提供了写屏障.相当于上述rmb()函数和wmb()函数的功能和.
read_barrier_depends():
是rmb()的变种,可以理解成rmb()一种优化.该屏障确保屏障前的读操作在屏障后的读操作之前完成,即那些相互依赖的读操作.
实例:
下面这个实例,其中a的初始值是1,b的初始值是2.
线程1 线程2 a = 3; - Mb(); - b = 4; c = b; - rmb(); - d = a;
如果不使用内存屏障,c可能接受了b的新值,而d接收了a原来的值.c可能等于4(我们期望的),而d可能等于1(不是我们期望的).因此,针对一些有顺序要求的寄存器操作的话,内存屏障是必须考虑的.