我需要在不同的进程之间交换一些变量,并通过共享内存来尝试。以下代码是此尝试的简化版本。该程序按预期工作,但我想确保交换不仅因为运气而有效。
我的主要问题是,将所有指针声明为volatile是否足够,以确保编译器无法优化内存读取?或者我是否需要插入一些额外的同步命令?
#include <sys/mman.h>
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <type_traits>
struct Exchange
{
int x;
};
int main()
{
int fd = open("/dev/shm/foobar", O_RDWR | O_CREAT, 0600);
if(fd == -1)
{
std::cerr << "Open failed\n";
return 1;
}
if(ftruncate(fd, sizeof(Exchange)))
{
close(fd);
std::cerr << "Resize failed\n";
return 1;
}
auto xch = static_cast<volatile Exchange*>(
mmap(0, sizeof(Exchange),
PROT_READ | PROT_WRITE, MAP_SHARED,
fd, 0));
if(!xch)
{
std::cerr << "no mapping\n";
return 1;
}
xch->x=23;
while(1)
{
// Do I need to insert some sync instruction here?
std::cout << xch->x << std::endl;
xch->x++;
msync((void*)(xch), sizeof(*xch), MS_SYNC);
sleep(1);
}
}
答案 0 :(得分:1)
由于您已将msync与MS_SYNC
结合使用,因此不再需要进一步同步。
必备的手册页部分:
msync()刷新对文件的内核副本所做的更改 使用mmap(2)映射到内存中回到文件系统。
MS_SYNC: 请求更新并等待它完成。
对于阅读,也不需要再进行同步。使用msync
将数据写回文件,该文件将文件的页面标记为“脏”,并在下次读取时,mmap机制再次读取文件的页面(使用更新的值)。
更多信息:
在您的示例中,如果您的地图不是页面对齐的,则可能无法创建mmap。作为地图大小/长度,请始终使用页面大小的倍数。