C语言volatile类型限定符

volatile关键字在嵌入式系统中用于标记易变的内存空间,防止编译器优化导致的问题。它确保每次对这类变量的访问都从内存中读取,避免因缓存一致性问题而读取到旧值。然而,当外设寄存器改变时,CPU可能仍从缓存读取,不直接访问外设。解决方案通常涉及硬件层面的缓存一致性协议,如MESI协议,确保CPU在访问外设时获取最新值。
摘要由CSDN通过智能技术生成

个人博客链接

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博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值