通过内存映射文件,可以在同一台机器的不同进程间共享数据。Windows提供了其他一些方法在进程间共享数据,但这些方法都是通过内存映射文件来实现的。因此,要在同一台机器中共享数据,内存映射文件是最高效的方法。
要使用内存映射文件,需执行下面三步:
1、创建或打开一个文件内核对象,该对象标识了我们想要用作内存映射文件的对象
打开或者创建文件内核对象
HANDLE hCFile = CreateFile(TEXT(".\\data.txt"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2、创建一个文件映射内核对象,告诉系统文件大小及打开文件的方式
HANDLE hMapFile = CreateFileMapping(hCFile, NULL, PAGE_READWRITE, 0, 1024*1024, _T("MotionCtrl"));
一个进程创建一个命名的文件映射内核对象,其他进程可以直接用OpenFileMapping打开该命名的对象
HANDLE hFMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, _T("MotionCtrl"));
3、告诉系统把文件映射对象的部分或全部映射到进程的地址空间
LPVOID pfile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 64*1024, 100);
文件偏移量必须是Windows系统分配粒度的整数倍,默认是64K。也就是说映射文件某个起始地址的多少字节数据到进程数据空间中,该起始地址必须是64K的整数倍。这里就是说将从文件64K大小的起始位置其映射100字节数据到进程空间中。最后的参数为0表示从该地址起将整个文件映射到进程空间。
4、撤销进程地址空间对文件数据的映射
UnmapViewOfFile(hMapFile);
hMapFile必须要跟CreateFileMapping返回的值相同,MapViewOfFile总是在系统中预定一块新的区域,不会释放之前预定的区域,所以如果要重新在进程中预定区域,必须先将原来的区域释放。
出于速度上考虑,系统会对文件数据页面进行缓存处理,这样处理文件映射视图时不需要随时更新磁盘上的文件。如果需要确保所做的修改已经被写入磁盘,可以调用FlushViewOfFile函数,
5、关闭映射对象和文件对象
程序执行完后关闭已经打开的资源
CloseHandle(hMapFile);
CloseHandle(hCFile);
6、WinCE5平台下内存映射允许的最大长度
WinCE5下所允许的最大映射长度为20K,这困扰了我很久,其他地方映射文件时都正常,映射一段160000(150K+)字节大小的内存时出问题,最后逐个试发现WinCE与Windows下内存映射的区别有两点:(1)、Windows下映射的起始地址必须是4K的倍数,否则报参数错,WinCE却可以是随意的起始地址;(2)、Windows下允许的映射长度是4G,WinCE最大只允许18K-19K。标记一下,以示警示。
char *pData = (char*)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 18*1024);