内存映射文件保留了一个地址空间区域,在需要的时候将他提交的物理存储器,他们之间的不同点是内存映射文件提交到物理存储器的数据来自磁盘上相应的文件,而不是系统页文件。一旦文件被映射,就可以认为整个文件被加载到了内存中,可以像访问内存一样访问文件的内容。可以使用内存映射来访问磁盘上的数据,还可以用内存映射文件实现多个进程间共享数据。
内存映射文件相关的函数包括,CreateFileMapping(),OpenFileMapping(),MapViewOfFile(),UnmapViewOfFile,FlushViewOfFile().
windows下进程的地址空间在逻辑上是相互隔离的,但在物理上却是重叠的。所谓重叠是指同一内存区域可能被多个进程同时使用。当使用CreateFileMapping创建命名的内存映射文件对象的时候,window即在物理内存申请一块大小指定的内存区域,返回文件映射对象的句柄hMap.为了能够访问这块内存区域必须调用MapViewOfFile()函数,促使Windows将此内存空间映射到进程的内存空间当中。当在其他进程访问这块内存区域的时候,则必须使用OpenFileMapping函数取得对应的句柄,并调用MapViewOfFile()函数得到此内存空间的一个映射。这样一来,系统就把同一块内存映射到了不同进程的地址空间中,达到了共享内存共享的目的。
HANDLE WINAPI CreateFileMapping(
_In_HANDLE hFile, //一个文件句柄,为-1的时候标识建立共享内存
_In_opt_LPSECURITY_ATTRIBUTES lpAttributes, //定义该内存映像是否可以继承
_In_DWORD flProtect, //该内存映像的保护类型PAGE_READONLY 或PAGE_READWRITE
_In_DWORD dwMaximumSizeHigh, //内存映射文件的大小
_In_DWORD dwMaximumSizeLow,
_In_opt_LPCTSTR lpName //内存映射文件的名字
);
LPVOID WINAPI MapViewOfFile(
__in HANDLE hFileMappingObject, //前面两个函数返回的内存映射文件的句柄
__in DWORD dwDesiredAccess, //指定的保护类型,可以是FILE_MAP_WRITE,FIEL_MAP_READ
__in DWORD dwFileOffsetHigh, //从文件哪个地方开始映射
__in DWORD dwFileOffsetLow,
__in SIZE_T dwNumberOfBytesToMap//要映射的字节数,如果为0则映射整个文件
);
HANDLE OpenFileMapping(
DWORD dwDesiredAccess, //指定的保护类型,FILE_MAP_WRITE,FILE_MAP_READ
BOOL bInheritHandle, //返回的句柄是否可继承
LPCTSTR lpName, //创建对象的时候使用的名字
下面的代码简单的实现了共享内存在进程间通信的过程。
#include<iostream>
#include<Windows.h>
using namespace std;
void main(int argc, char* argv[])
{
char szName[] = "ShareMem";
char szDada[] = "123456";
LPVOID pBuffer;//共享内存指针
HANDLE hMap = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, szName);
if (hMap != NULL)
{
pBuffer = ::MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
cout << "读出共享内存数据;" <<(char *) pBuffer << endl;
}
else
{
hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, strlen(szDada) + 1, "ShareMem");
pBuffer = ::MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
strcpy((char*)pBuffer, szDada);
cout << "写入共享内存数据:" << (char*)pBuffer << endl;
}
getchar();
::UnmapViewOfFile(pBuffer);
::CloseHandle(hMap);
return;
}
只要创建的共享内存的进程没有关闭hMap,以后运行的进程就可以读出共享内存里面的数据。
在命令行窗口运行同一个程序两次,getchar()的作用是使程序处于挂起状态