为什么说段是内存映射的一种方式?
答案:1 悬赏:20 手机版
解决时间 2021-04-23 09:47
- 提问者网友:姑娘长的好罪过
- 2021-04-22 15:05
为什么说段是内存映射的一种方式?
最佳答案
- 五星知识达人网友:酒醒三更
- 2021-04-22 15:39
在Win32中,每个进程有自己的地址空间,一个进程不能轻易地访问另一个进程地址空间中的数据,所以不能像16位Windows那样做。Win32系统允许多个进程(运行在同一计算机上)使用内存映射文件来共享数据。实际上,其他共享和传送数据的技术,诸如使用SendMessage或者PostMessage,都在内部使用了内存映射文件。
这种数据共享是让两个或多个进程映射同一文件映射对象的视图,即它们在共享同一物理存储页。这样,当一个进程向内存映射文件的一个视图写入数据时,其他的进程立即在自己的视图中看到变化。但要注意,对文件映射对象要使用同一名字。
以下是一段使用内存映射文件的代码:
创建:
HANDLE s_hFileMap = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, 4*1024,_TEXT("MyCustShareData"));
(此函数寻找一个名字为"MyCustShareData"的内存映射文件,不存在则创建,存在则返回已有的句柄,所以当返回值不为空的话,还须检查GetLastError,如果得到ERROR_ALREADY_EXISTS,则表明该名字的内存映射文件已经存在,并未创建成功)
读写:
HANDLE hFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, _TEXT("MyCustShareData"));//最后一个参数为名字,必须与创建的相同
if(hFile != NULL)
{
LPVOID lpView = MapViewOfFile(hFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);//将内存映射文件的一个视图映射到当前的地址空间
if ((int *)lpView != NULL)
{
int sheardata = (int*)lpview; //读
(int *)lpview = 88; //写
}
UpmapViewOfFile((LPVOID) lpview);
}
CloseHandle(hFile);
其中MapViewOfFile的原型如下所示:
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // 映射文件对象的句柄
DWORD dwDesiredAccess, // 访问模式
DWORD dwFileOffsetHigh, // 位移的高位
DWORD dwFileOffsetLow, // 位移的低位(与前一个参数一起构成64位的位移量)
SIZE_T dwNumberOfBytesToMap // 映射量(单位为Byte,当设为0时表示映射整个文件)
);
您所提到的mapviewoffileEx函数的原型如下所示:
LPVOID MapViewOfFileEx(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap,
LPVOID lpBaseAddress
);
其中前五个参数的含义同上,第六个参数给出一个调用映射文件的进程的地址,要求文件映射从该地址开始。这个值必须是一个系统内存分配的最小粒度的整数倍,否则此函数调用失败。要获得内存分配的粒度,可以调用GetSystemInfo函数。如果指定的内存地址没有足够的空间,则函数也失败。
如果此参数的值设为NULL,则操作系统选择从何地址开始进行文件映射,这样,函数的功能与MapViewOfFile相同
这种数据共享是让两个或多个进程映射同一文件映射对象的视图,即它们在共享同一物理存储页。这样,当一个进程向内存映射文件的一个视图写入数据时,其他的进程立即在自己的视图中看到变化。但要注意,对文件映射对象要使用同一名字。
以下是一段使用内存映射文件的代码:
创建:
HANDLE s_hFileMap = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, 4*1024,_TEXT("MyCustShareData"));
(此函数寻找一个名字为"MyCustShareData"的内存映射文件,不存在则创建,存在则返回已有的句柄,所以当返回值不为空的话,还须检查GetLastError,如果得到ERROR_ALREADY_EXISTS,则表明该名字的内存映射文件已经存在,并未创建成功)
读写:
HANDLE hFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, _TEXT("MyCustShareData"));//最后一个参数为名字,必须与创建的相同
if(hFile != NULL)
{
LPVOID lpView = MapViewOfFile(hFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);//将内存映射文件的一个视图映射到当前的地址空间
if ((int *)lpView != NULL)
{
int sheardata = (int*)lpview; //读
(int *)lpview = 88; //写
}
UpmapViewOfFile((LPVOID) lpview);
}
CloseHandle(hFile);
其中MapViewOfFile的原型如下所示:
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // 映射文件对象的句柄
DWORD dwDesiredAccess, // 访问模式
DWORD dwFileOffsetHigh, // 位移的高位
DWORD dwFileOffsetLow, // 位移的低位(与前一个参数一起构成64位的位移量)
SIZE_T dwNumberOfBytesToMap // 映射量(单位为Byte,当设为0时表示映射整个文件)
);
您所提到的mapviewoffileEx函数的原型如下所示:
LPVOID MapViewOfFileEx(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap,
LPVOID lpBaseAddress
);
其中前五个参数的含义同上,第六个参数给出一个调用映射文件的进程的地址,要求文件映射从该地址开始。这个值必须是一个系统内存分配的最小粒度的整数倍,否则此函数调用失败。要获得内存分配的粒度,可以调用GetSystemInfo函数。如果指定的内存地址没有足够的空间,则函数也失败。
如果此参数的值设为NULL,则操作系统选择从何地址开始进行文件映射,这样,函数的功能与MapViewOfFile相同
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯