内存映射文件,是由一个文件到一块内存的映射。与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自一个已经存在的磁盘上的文件,而且在对该文件进行操作之前必须首先对文件进行映射。
另外,内存映射文件是由一个文件到进程地址空间的映射,Win32中,每个进程有自己的地址空间,一个进程不能轻易地访问另一个进程地址空间的数据,内存映射文件允许多个进程共享数据。
下面给出使用内存映射文件的一般方法:
(1)创建文件对象
首先要通过CreateFile()函数来创建或打开一个文件内核对象,这个对象标识了磁盘上将要用作内存映射文件的文件。在用CreateFile()将文件映像在物理存储器的位置通告给操作系统后,只指定了映像文件的路径,映像的长度还没有指定。
(2)创建文件映射对象
为了指定文件映射对象需要多大的物理存储空间还需要通过CreateFileMapping()函数来创建一个文件映射内核对象,以告诉系统文件的尺寸以及访问文件的方式。
(3)将文件数据映射到进程的地址空间
由MapViewOfFile()函数负责通过系统的管理而将文件映射对象的全部或部分映射到进程地址空间。
(4)清除和使用过资源的释放
通过UnmapViewOfFile()完成从进程的地址空间撤消文件数据的映像、通过CloseHandle()关闭前面创建的文件映射对象和文件对象。
#include <iostream>
#include <fcntl.h>
#include <io.h>
#include <afxwin.h>
using namespace std;
void* g_pszMapView;
BOOL FileMapping(PCSTR pszPathName)
{
/*创建文件对象*/
HANDLE hFile=CreateFile(
pszPathName, /*文件名*/
GENERIC_READ|GENERIC_WRITE, /*访问模式:对文件进行读写操作*/
FILE_SHARE_READ|FILE_SHARE_WRITE, /*共享模式*/
NULL, /*安全属性*/
OPEN_ALWAYS, /*如何创建:CREATE_NEW-创建文件,如文件存在会出错;
CREATE_ALWAYS:创建文件,会改写前一个文件
OPEN_EXISTING: 文件必须已经存在
OPEN_ALWAYS : 如文件不存在则创建它
TRUNCATE_EXISTING:将现有文件缩短为零长度*/
FILE_ATTRIBUTE_NORMAL, /*文件属性*/
0);
if (INVALID_HANDLE_VALUE==hFile)
{
printf("创建文件对象失败,错误代码:%drn", GetLastError());
return FALSE;
}
DWORD dwFileSize=GetFileSize(hFile,NULL);/*获取文件大小*/
size_t view_size=1024*256;
/*创建文件内存映射对象。*/
HANDLE hMapFile=CreateFileMapping(
hFile, /*需要映射的文件对象句柄*/
NULL, /*内存映射文件的安全属性*/
PAGE_READWRITE, /*对映射文件的保护类型,PAGE_READONLY:只读;PAGE_READWRITE:可读写*/
0, /*这两个参数共同指定内存映射文件的长度,若函数创建共享内存,则需要为这两个参数指定值*/
view_size, /*否则,均设置为0,表示内存映射文件长度与已经存在的文件长度一样*/
NULL); /*内存映射文件名*/
if(hMapFile==INVALID_HANDLE_VALUE)
{
printf("Can't create file mapping.Error%drn", GetLastError());
CloseHandle(hFile);
return FALSE;
}
/* 把文件数据映射到进程的地址空间*/
g_pszMapView=MapViewOfFile(
hMapFile, /*内存映射文件的对象句柄*/
FILE_MAP_ALL_ACCESS, /*指定保护类型*/
0, /*从文件的指定地址开始映射*/
0, /*指定映射停止的文件指针地址*/
0); /*需要映射的字节数,若为0则映射整个文件*/
if (!g_pszMapView)
{
printf("Can't Read RBC Data of shared memory file,error code:%d.",GetLastError());
CloseHandle(hFile);
CloseHandle(hMapFile);
return FALSE;
}
//结束
//UnmapViewOfFile(g_pszMapView); //撤销映射
//CloseHandle(hFile); //关闭文件
/*至此,就获得了外部文件pszPathName在内存地址空间的映射,*/
return TRUE;
}
int main()
{
FileMapping("c:\\test11.txt");
char cWrite[]="3ting";
const int nLen=sizeof(cWrite);
char* Temp=(char*)g_pszMapView;
strcat(Temp,cWrite);
char cRead[nLen];
//读数据
memcpy(cRead,g_pszMapView,nLen-1);
cout<<cRead<<endl;
return ;
}