一:先说 volatile,静态乱序
-
C/C++ 语言中的volatile关键字作用?
1.易变性:volatile告诉编译器,某个变量是易变的,当编译器遇到这个变量的时候,只能从变量的内存地址中读取这个变量,不可以从寄存器、或者其它任何地方读取。
2.顺序性:两个包含volatile变量的指令,编译后不可以乱序。注意是编译后不乱序,但是在执行的过程中还是可能会乱序的,这点需要由其它机制来保证,例如memory- barriers。
上面提到的俩个点已经全面覆盖了c/c++下volatile的全部功能。这里特别说明的是各个语言下volatile的意义和功能作用是不一样的,在java下volatile的功能要比上述提到的功能还要强大(增加了内存屏障)。
例子:没有使用volatile
uint8_t * p_reg = (uint8_t *) 0x1234;
// Wait for register to read non-zero
do { ... } while (0 == *p_reg)
mov p_reg, #0x1234
mov a, @p_reg
loop:
...
bz loop
使用volatile
uint8_t volatile * p_reg = (uint8_t volatile *) 0x1234;
The assembly language now looks like this:
mov p_reg, #0x1234
loop:
...
mov a, @p_reg
bz loop
volatile 和 指针的组合基本是这样几种,其实和const是一个语法
volatile uint16_t x;
uint16_t volatile y;
//上面俩种写法一个效果
volatile uint8_t * p_reg;
uint8_t volatile * p_reg;
//上面俩种写法一个效果,修饰指针指向的内容
uint16_t * volatile p_x;//修饰指针本身
二:再说动态乱序
动态乱序的根源是什么,是cpu为了速度快,进行了乱序执行,具体而言乱序执行究竟是什么那?那就是cpu会做简单的判断,在执行的时候会乱序执行,一些阻塞的操作会后执行,执行完成后在排序。这就导致了程序执行并不是安装我们代码写的顺序执行。
动态乱序的解决方案就是内存屏障,一道栅栏,拦住了。
其他链接
https://blog.csdn.net/chunlongyu/article/details/53304524
https://barrgroup.com/embedded-systems/how-to/c-volatile-keyword