volatile 能否解决缓存一致性问题
为何会产生这样的疑问,还得从一个工作中的 Bug 说起。在使用 PMP(Physical Memory Protect)对物理内存进行保护时,无法成功保护,简单来说 PMP 可以对一段物理内存设置保护,如保护这段内存不可写。测试时,先对这段内存写入0x1234
,再读取这段内存。如果读取的值为0x0
表示保护成功,但实际总能成功读取0x1234
。
volatile int test;
test = read(0xFF740000);
print("Before = %x\n", test); // 保护之前数据 Before = 0x1111
PMP(0xFF740000, 0x400); // 保护这段内存不可写
write(0xFF740000, 0x1234); // 写入数据
test = read(0xFF740000);
print("After = %x\n", test); // 预期读取为0x0,实际总能成功读取0x1234
因为读取的变量test
设置为volatile
,所以按照以往的理解,系统总是重新从它所在的内存读取数据,这里应该能正确读取出数据。
但是忽略了一点,当使用volatile
变量时,CPU 只是不再使用寄存器中的值,直接去内存中读取数据,这里的内存实际上是包括 Cache 的。
所以当数据被 Cached 之后,当再次读取时,CPU 可能会直接读取 Cached 的数据,而不是去读取真正内存中的数据。因此,volatile 不能解决缓存一致性问题。
关于 Cache 的详细信息,请参考CPU Cache 高速缓存 - 如云泊。