同步mmaped区域访问的正确方法是什么
What is the correct way to synchronize the access of a mmaped region
我需要在不同的进程之间交换一些变量,并通过共享内存尝试。下面的代码是这种尝试的简化版本。该程序按预期运行,但我想确保交换不只是因为运气。
我的主要问题是,是否足以将所有指针声明为 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);
}
}
由于您已经将 msync 与 MS_SYNC
结合使用,因此不再需要进一步同步。
基本手册页部分:
msync() flushes changes made to the in-core copy of a file that was
mapped into memory using mmap(2) back to the filesystem.
MS_SYNC:
Requests an update and waits for it to complete.
对于阅读,也不需要更多的同步。使用 msync
将数据写回文件,标记文件页面 "dirty",并且在下一次读取时,mmap 机制(使用更新后的值)再次读取文件页面。
更多信息:
在您的示例中,如果您的地图未与页面对齐,则可能无法创建 mmap。作为地图大小/长度,始终使用页面大小的倍数。
我需要在不同的进程之间交换一些变量,并通过共享内存尝试。下面的代码是这种尝试的简化版本。该程序按预期运行,但我想确保交换不只是因为运气。
我的主要问题是,是否足以将所有指针声明为 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);
}
}
由于您已经将 msync 与 MS_SYNC
结合使用,因此不再需要进一步同步。
基本手册页部分:
msync() flushes changes made to the in-core copy of a file that was mapped into memory using mmap(2) back to the filesystem.
MS_SYNC: Requests an update and waits for it to complete.
对于阅读,也不需要更多的同步。使用 msync
将数据写回文件,标记文件页面 "dirty",并且在下一次读取时,mmap 机制(使用更新后的值)再次读取文件页面。
更多信息:
在您的示例中,如果您的地图未与页面对齐,则可能无法创建 mmap。作为地图大小/长度,始终使用页面大小的倍数。