内存映射方法CreateFileMapping、MapViewOfFile、UnmapViewOfFile

内存映射使用方法
1.先行打开物理文件
hFile = CreateFileCreateFile(szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
2.根据CreateFile返回的句柄创建内存映射
hMapping = CreateFileMapping(hFile,0,PAGE_READONLY,0,0,“a”);
3.将内存映射文件映射在内存中返回可操作的地址
ReadString = MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0);
4.释放内存映射地址
UnmapViewOfFile(ReadString);
5.关闭文件映射句柄
CloseHandle(hMapping);
6.关闭物理文件句柄
CloseHandle(hFile);
对内存映射的操作方法步骤

CreateFileMapping 创建一个文件内核内存映射
函数原型

HANDLE CreateFileMapping(
HANDLE hFile, //物理文件句柄
LPSECURITY_ATTRIBUTES lpAttributes, //安全设置
DWORD flProtect, //保护设置
DWORD dwMaximumSizeHigh, //高位文件大小
DWORD dwMaximumSizeLow, //低位文件大小
LPCTSTR lpName //共享内存名称
);

返回值:是一个句柄HANDLE,这个句柄用于MapViewOfFile函数和UnmapViewOfFile函数使用
返回值有可能出错,出错的可能情况如下几种GetLastError()取得:
ERROR_FILE_INVALID 物理文件句柄失败
ERROR_INVALID_HANDLE 创建文件内核映射内存失败
ERROR_ALREADY_EXISTS 共享内存名称已存在,重名了

函数参数列表:
1.HANDLE hFile, //物理文件句柄,使用CreateFile取得物理文件句柄,如果创建的内存映射和物理文件无关,可以将参数设置为INVALID_HANDLE_VALUE,脱离与实体文件的关联
2.LPSECURITY_ATTRIBUTES lpAttributes, //安全设置
通常情况使用默认的安全属性NULL,如果是win2k系统映射内存给网络使用时需要设置安全属性
3.DWORD flProtect, //保护设置
PAGE_READONLY 以只读方式打开映射
PAGE_READWRITE 以可读、可写方式打开映射
PAGE_WRITECOPY 为写操作留下备份
可组合使用下述一个或多个常数:
SEC_COMMIT 为文件映射一个小节中的所有页分配内存
SEC_IMAGE 文件是个可执行文件
SEC_RESERVE 为没有分配实际内存的一个小节保留虚拟内存空间
4.DWORD dwMaximumSizeHigh, //高位文件大小
5.DWORD dwMaximumSizeLow, //低位文件大小
以上两个参数由两个32位表示一个64位的文件,手动指定内存大小,如果都设置为0,那么就表示用物理文件的实际大小进行内存映射
6.LPCTSTR lpName //共享内存名称
如果设置名称,那么内存映射将和其他进程共享内存使用,共享方式是用共享内存名称来实现的。

MapViewOfFile 将一个文件映射对象映射到当前应用程序的地址空间。
MapViewOfFileEx允许我们指定一个基本地址来进行映射。
函数原型

LPVOID MapViewOfFile(
  HANDLE hFileMappingObject, //内存映射文件产生句柄
  DWORD dwDesiredAccess, //对文件映射访问的权限
  DWORD dwFileOffsetHigh, //偏移量高位
  DWORD dwFileOffsetLow,//偏移量低位
  DWORD dwNumberOfBytesToMap //指定要映射的文件的字节数。如果将此参数设置为零,则将映射整个文件。
);

返回值:
如果函数成功将返回内存映射的地址;失败使用GetLastError()取得
参数列表说明:
1.HANDLE hFileMappingObject 由CreateFileMapping创建句柄
2.DWORD dwDesiredAccess 映射对象的文件数据的访问方式,而且同样要与CreateFileMapping()函数所设置的保护属性相匹配。 可取以下值:
映射对象的文件数据的访问方式,而且同样要与CreateFileMapping()函数所设置的保护属性相匹配。 可取以下值:
FILE_MAP_ALL_ACCESS 等价于CreateFileMapping的 FILE_MAP_WRITE|FILE_MAP_READ. 文件映射对象被创建时必须指定PAGE_READWRITE 选项.
FILE_MAP_COPY 可以读取和写入文件.写入操作会导致系统为该页面创建一份副本.在调用CreateFileMapping时必须传入PAGE_WRITECOPY保护属性.
FILE_MAP_EXECUTE 可以将文件中的数据作为代码来执行.在调用CreateFileMapping时可以传入PAGE_EXECUTE_READWRITE或PAGE_EXECUTE_READ保护属性.
FILE_MAP_READ 可以读取文件.在调用CreateFileMapping时可以传入PAGE_READONLY或PAGE_READWRITE保护属性.
FILE_MAP_WRITE 可以读取和写入文件.在调用CreateFileMapping时必须传入PAGE_READWRITE保护属性.
3.DWORD dwFileOffsetHigh, //偏移量高位
4. DWORD dwFileOffsetLow,//偏移量低位
5. DWORD dwNumberOfBytesToMap //指定要映射的文件的字节数。
如果将此参数设置为零,则将映射整个文件。

UnmapViewOfFile停止文件映射

BOOL WINAPI UnmapViewOfFile(_In_LPCVOID lpBaseAddress);

这里的lpBaseAddress是由MapViewOfFile产生的内存地址

如下例子:

#include <windows.h>
#include <stdio.h>

BOOL ReadFileToMemMapping(LPCTSTR szFileName);

int main(int argc,LPTSTR argv[])
{
	if(argc < 2)
	{
		printf("用法错误,Usage: %s 文件名 ...\n",argv[0]);
		return 0;
	}
	for(int i = 1; i < argc;i++)
	{
		ReadFileToMemMapping(argv[i]);
	}
	return 0;
}

BOOL ReadFileToMemMapping(LPCTSTR szFileName)
{
	BOOL bRet = szFileName && lstrlen(szFileName);
	HANDLE hFile = CreateFile(szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	HANDLE hMapping;
	LPVOID ReadString;

	if(!bRet)
	{
		printf("文件名为空!\n");
		return bRet;
	}

	if(hFile == INVALID_HANDLE_VALUE) 
	{
		printf("文件:%s打开失败!\n",szFileName);
		return bRet;
	}

	hMapping = CreateFileMapping(hFile,0,PAGE_READONLY,0,0,"a");

	if(hMapping == INVALID_HANDLE_VALUE)
	{
		printf("文件映射打开失败!\n");
		CloseHandle(hFile);
		return false;
	}

	ReadString = MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0);
	if(!ReadString)
	{
		printf("读取文件映射数据失败!\n");
		CloseHandle(hMapping);
		CloseHandle(hFile);
		return false;
	}

	printf("我读到的内存文件为%s\n",(LPTSTR)ReadString);

	UnmapViewOfFile(ReadString);
	CloseHandle(hMapping);
	CloseHandle(hFile);


	return bRet;


}
发布了23 篇原创文章 · 获赞 1 · 访问量 6138
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览