个人博客链接
volatile
在嵌入式系统中,部分内存空间可能是 易变的
(volatile),保存在这种内存空间中的值可能在程序运行期间发生改变,即使程序本身并没有修改这些值。比如说,外设的一些寄存器会映射到内存空间(即统一编址),而这些寄存器可能会被外设自己修改,比如说状态寄存器。
volatile
类型限定符可以告诉编译器,程序中的某些数据是 易变的
,volatile
通常用于指向易变内存空间的指针的声明中,比如说
volatile int *p;
使用 volatile
的一个作用在于,可以防止编译器对该变量的优化,从而避免程序出现问题。比如说有一个程序,最开始反复读取外设的状态寄存器,当状态寄存器的值表示外设已经完成对应操作后,程序就读取外设的数据寄存器。程序反复读取外设状态寄存器对应的地址,在编译器看来,程序并没有修改这个地址处的值,因此编译器可能会进行优化,即只在最开始读取一次,并把它放到寄存器中,后面对这个地址的读取都优化成对这个寄存器的读取,但是这样就会出现问题,如果最开始外设并没有完成相关操作,由于优化后的程序只在最开始读取了一次状态寄存器,即使后面状态寄存器的值更新了,CPU也并不会重新访问对应的内存地址,因此CPU就会一直认为外设没有完成相关操作,从而陷入死循环。使用 volatile
声明这个内存地址,编译器就不会进行这样的优化了。
新的问题
volatile可以防止编译器把反复load一个内存地址最终优化为只load一次,但是load指令硬件上也是先访问的cache,而不是实际外设中的寄存器,如果外设寄存器值发生改变,那么cache中的值还是旧的,那么CPU还是会读到一个旧值。外设寄存器的修改可能是外设自己执行的(比如状态寄存器),不走总线,cache也没法通过监听总线来保持一致性,那么这个问题是怎么解决的呢?难道是检测到内存地址是外设的时候,就不走cache了吗?
目前看到一个说法是 (14条消息) linux cache 一致性_dake_160413的博客-CSDN博客