C17、内存映射文件
来源:互联网 发布:真无线耳机 推荐 知乎 编辑:程序博客网 时间:2024/06/01 10:18
一、使用目的:
n 系统加载执行.exe 和DLL文件(节省页文件空间,快速启动);
n 访问磁盘文件而不必进行I/O操作和缓存;
n 进程间共享数据(进程间通讯最有效的方法)。
二、默认情况下,全局数据和静态数据不能被同一个.exe 或DLL文件的多个映像共享。但可以改变(但不鼓励使用)。改变的方法:
n 每个.exe 或DLL文件的映像都由许多节组成,如:.text, .bss, .data等。 使用DumpBin /Headers myPrg.exe可以查看.exe或DLL映射文件中各个节的列表。
n 可以创建自己的节,eg:// 创建名为mynode的节,包含单个LONG值:
#pragma data_seg(“mynode”)
LONG g_lMyData = 0;
#pragma data_seg()
n 如果想共享这个节,可以在链接程序使用开关:/SECTION,eg:
#pragma comment(linker, “/SECTION:mynode,RWS”)
其中:RWS表示Read-Write-Share属性。
三、使用内存映射文件:
1. 创建/打开一个文件内核对象(用于标识做映射的文件);
HANDLE CreateFile(
PCTSTR pszFileName, // 文件名
DWORD dwDesiredAccess, //0-用于获取文件属性;GENERIC_READ,WRITE
DWORD dwShareMode, // FILE_SHARE_READ, WRITE
PSECURITY_ATTRIBUTES psa, // NULL 默认安全属性
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
u 成功返回文件内核对象句柄;失败返回INVALID_HANDLE_VALUE。
2. 创建一个文件映射内核对象(可以设定文件大小、访问权限);
HANDLE CreateFileMapping(
HANDLE hFile, // 由CreateFile返回的文件句柄
PSECURITY_ATTRIBUTES psa, // NULL 默认安全属性
DWORD fdwProtect, // 一般保护属性:PAGE_READONLY, READWRITE,WRITECOPY以及节保护属性:SEC_NOCACHE(无高速缓存,设备驱动程序使用),_IMAGE(可移植的可执行文件),_RESERVE,_COMMIT(二者互斥,不用于内存映射数据文件)
DWORD dwMaximumSizeHigh, // 文件最大字节数(64位)的 高32位
DWORD dwMaximumSizeLow, // 低32位。如果等于文件大小,=0
PCTSTR pszName);// 进程间共享名,可以=NULL
u 成功:返回对象句柄;失败:NULL。
3. 映射全部/部分到进程地址空间。
PVOID MapViewOfFile(
HANDLE hFileMappingObject, // CreateFileMapping返回的句柄
DWORD dwDesiredAccess, // FILE_MAP_WRITE, _READ, _ALL_ACCESS, _COPY (Win98必须)
DWORD dwFileOffsetHigh, // 64位文件偏移位置的 高32位
DWORD dwFileOffsetLow, // 低32位;必须为分配粒度的倍数(64K)
SIZE_T dwNumberOfBytesToMap); // 映射的字节数,=0将映射的文件尾为止
u 成功:返回地址空间的首地址,失败:NULL。
u 如果用FILE_MAP_COPY,系统马上提交页文件(但不一定使用);一旦有写入,系统马上将这个有操作的页面的原始数据拷贝到页文件的相应页面,你只写入到该拷贝中(原始文件无变化)
4. 撤销映像;
BOOL UnmapViewOfFile(PVOID pvBaseAddress); // MapViewOfFile返回的首地址。
因为系统的高速缓存,需强制系统将修改过的数据的一部分或全部重新写入磁盘:
BOOL FlushViewOfFile(
PVOID pvAddress, // 映射的首地址,函数自动将其圆整为页面边界值
SIZE_T dwNumberofBytesToFlush);// 刷新的字节数
u 但,网络服务器因为高速缓存,并不保证写入远程磁盘。若要保证服务器写入,在CreateFile中传递FILE_FLAG_WRITE_THROUGH,并使用FlushViewOfFile。
u 如果使用FILE_MAP_COPY映射视图,你对文件数据的任何修改实际上是对页文件中的拷贝所作的修改,FlushViewOfFile不会刷新磁盘文件。若要保留修改,可以用同一个文件创建另一个映射(使用PAGE_READWRITE),然后用FILE_MAP_WRITE映射到地址空间。扫描第一个视图寻找带有PAGE_READWRITE保护属性的页面(在写入操作时,系统将页面的保护属性从PAGE_WRITECOPY改为PAGE_READWRITE),调用MoveMemory将数据页面从第一个视图拷贝到第二个视图,FlushViewOfFile保存第二个视图。
5. 关闭文件映射内核对象:CloseHandle(hFileMapping);
早期关闭内核对象:如果不用创建多个文件映射对象或映射多个视图,可以在调用MapViewOfFile后立即关闭文件对象和文件映射内核对象。
6. 关闭文件(内核)对象:CloeseHandle(hFile)。
四、文件倒序实例程序(FileRev):
u 文本文件的结尾无0结束符,而_strrev(_wcsrev)函数要求以0结尾的字符串。在文件的结尾添加0:
a) 在CreateFileMapping(…… dwFileSize+ sizeof(WCHAR), NULL); // 映射的字节数是文件长+一个宽字符的大小;
b) 输入文本结尾字符=0;
c) 文件转换完成后,使用SetFilePointer,SetEndOfFile重新设置文件结尾位置(=原文件大小)。
d) 因为使用了PAGE_READWRITE属性,所有不用FlushViewOfFile。
u 文本的换行符是"/r/n",使用_strrev后转换成了"/n/r",所有要转回来。遍历所有字符,查找’/n’将连续的两个字符换成"/r/n"。(UNICODE 是L’/n’)。
五、超大文件的操作注意事项:
u __int64 qwFileSize = GetFileSize分别返回高32位和低32位值移位加;
u 按粒度大小进行映射视图时的地址偏移;
u 测试内存分配粒度,按粒度大小分别映射视图;文件尾部少于粒度大小,则按实际大小映射视图
一、内存映射文件与数据视图的相关性:只要是映射相同的文件映射对象,系统就会确保映射视图数据的相关性(在多线程中也一样)。
二、可以设定内存映射文件的基地址,使用MapViewOfFileEx。
u 一般用于与其他进程共享数据时。如果内存映射文件使用了链表结构,不使用相同的基地址,遍历时会出错!不过使用Mircrosoft的编译器__based关键字也能解决,但不建议使用。
u 他比MapViewOfFile多一个pvBaseAddress参数,是你的目标地址(在WIN2000下应该是分配粒度边界64KB的倍数,否则出错,GetLastError返回1132:ERROR_MAPPED_ALIGNMENT,WIN98系统自动圆整)。如果系统无法映射到该位置(文件太大,且与另一个保留的地址重叠),也出错(返回NULL)。如果使用pvBaseAddress = NULL,则与MapViewOfFile运行结果完全相同。
三、页文件支持的内存映射文件(非磁盘文件支持):
u 不需要用CreateFile返回文件句柄;
u 调用CreateFileMapping,用INVALID_HANDLE_VALUE作为hFile的参数;
u 如果进程间共享,调用CreateFileMapping或OpenFileMapping,用相同的字符串作为pszName参数;
u 使用结束后,CloseHandle。
u 所以,如果在打开文件失败时未检查返回值,系统将创建的是“页文件支持的内存映射文件”。
四、稀疏提交的内存映射文件(要求NT文件系统):
u 调用CreateFileMapping,fdwProtect使用SEC_RESERVE或SEC_COMMIT标志创建页文件支持的内存映射文件(hFile = INVALID_HANDLE_VALUE)
u CreateFileMapping用SEC_RESERVE时,系统并不从页文件中提交物理存储器,只返回文件映射对象的句柄,MapViewOfFile(Ex)只保留地址空间区域,也不提交物理存储器,(这时,任何访问都会违例!);
u 调用VirtualAlloc提交物理存储器(pvAddress = MapViewOfFile返回地址)。(虽然,WIN98下,VirtualAlloc要求内存地址位于0x00400000~0x7FFFFFFF,内存映射文件的地址位于0x80000000~0xBFFFFFFF,但不会产生错误);
u WIN2000下,不能用VirtualFree释放使用SEC_RESERVE保留的存储器;但是,WIN98允许;
u NT文件系统(NTFS 5)提供了对稀疏文件的支持。参见示例:MMFSparse。
- C17、内存映射文件
- c17
- 内存映射:内存映射文件
- 内存映射:内存映射文件
- 内存映射文件
- 内存映射文件 续
- 内存映射文件 尾
- 内存映射文件
- 使用内存映射文件
- 内存映射文件
- 内存映射文件
- 内存映射文件技术
- 内存映射文件
- 内存映射文件
- 内存映射文件
- 内存映射文件
- 使用内存映射文件
- 内存映射文件技术
- java 3D错误:Fail to create reference rasterizer 3D Device
- oracle自带的操作文件的包UTL_FILE介绍
- CSS浏览器兼容问题整理
- C16、线程的堆栈
- lucene入门-使用JE中文分词
- C17、内存映射文件
- 一道以前的面试题
- lucene入门-简单的WEB搜索界面
- 在JS中使用trim()方法
- C18、堆栈
- 数据恢复
- OCL和MDA
- QT初探
- Marry christmas