我在多计算机环境中工作,其中 2 台计算机将通过 32 位 PCI 总线访问同一内存。
第一台电脑只会写入32bit int。
*int_pointer = number;
第二台电脑只会读取32位的int。
number = *int_pointer;
两个操作系统/CPU 都是 32 位架构。
带有 PCI 的计算机是基于 Intel 的。
PCI卡上的计算机是power PC。
我担心的情况是,如果只写计算机在读取计算机读取它的同时更改变量,导致读取计算机的数据无效。
我想知道在多台计算机上是否保留了读取/写入内存中相同位置的原子性。
如果是这样,以下是否会阻止竞争条件:
number = *int_pointer;
while(*int_pointer != number) {
number = *int_pointer;
}
我可以保证写入每 16ms* 发生一次,读取随机发生。
*由于两台计算机的计时器不同,时间会有所漂移。
最佳答案
没有足够的信息来明确回答这个问题。
如果任何一个 CPU 决定将内存缓存在 *int_pointer
处,这将始终失败,并且您的额外代码将无法修复任何竞争条件。
假设两个 CPU 都知道 *int_pointer
处的内存是不可缓存的,并且该位置 *int_pointer
在 4 字节/32 上对齐-位边界 AND PCI 卡上的 CPU 具有 32 位内存接口(interface),AND 指针声明为指向 volatile
并且您的两个 C 编译器都正确实现了 volatile,那么更新很可能是原子的。
如果不满足上述任何条件,结果将不可预测,您的“种族检测”代码可能无法正常工作。
编辑以解释为什么需要 volatile
:
这是使用 -O4
且没有 volatile
限定符编译为 MIPS 汇编程序的竞争条件代码。 (我使用了 MIPS,因为生成的代码比 x86 代码更容易阅读):
int nonvol(int *ip) {
int number = *ip;
while (*ip != number) {
number = *ip;
}
return number;
}
反汇编输出:
00000000 <nonvol>:
0: 8c820000 lw v0,0(a0)
4: 03e00008 jr ra
编译器已经优化了 while
循环,因为它知道 *ip
不能改变。
下面是 volatile
和相同的编译器选项会发生什么:
int vol(volatile int *ip) {
int number = *ip;
while (*ip != number) {
number = *ip;
}
return number;
}
反汇编输出:
00000008 <vol>:
8: 8c820000 lw v0,0(a0)
c: 8c830000 lw v1,0(a0)
10: 1443fffd bne v0,v1,8 <vol>
14: 00000000 nop
18: 03e00008 jr ra
现在 while
循环没有被优化掉,因为使用 volatile
告诉编译器 *ip
可以随时改变。
关于c - 读/写原子性是否适用于多计算机内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16660489/