使用windows内存-内存映射文件
内存映射文件
和虚拟内存一样,内存映射文件可以用来保留一个进程地址区域;但是,与虚拟内存不同,它提交的不是物理内存或是虚拟页文件,而是硬盘上的文件。将文件映射成内存,我们可以像使用内存一样使用文件.
使用场合
它有三个主要用途:
系统加载EXE和DLL文件
操作系统就是用它来加载exe和dll文件建立进程,运行exe。这样可以节省页文件和启动时间。
访问大数据文件
如果文件太大,比如超过了进程用户区2G,用fopen是不能对文件进行操作的。这时,可用内存映射文件。对于大数据文件可以不必对文件执行I/O操作,不必对所有文件内容进行缓存。
进程共享机制
内存映射文件是多个进程共享数据的一种较高性能的有效方式,它也是操作系统进程通信机制的底层实现方法。RPC、COM、OLE、DDE、窗口消息、剪贴板、管道、Socket等都是使用内存映射文件实现的。
相关函数介绍
CreateFile(文件名,访问属性,共享模式,…)
作用:创建文件内核对象API
其中,访问属性有:
0 不能读写 (用它可以访问文件属性)
GENERIC_READ
GENERIC_WRITE
GENERIC_READ|GENERIC_WRITE;
共享模式:
0 独享文件,其他应用程序无法打开
FILE_SHARE_WRITE
FILE_SHARE_READ|FILE_SHARE_WRITE
这个属性依赖于访问属性,必须和访问属性不冲突。
当创建失败时,返回INVALID_HANDLE_VALUE。
HANDLE CreateFileMapping(Handle 文件,PSECURITY_ATTRIBUTES 安全属性,DWORD 保护属性,DWORD 文件大小高32位,DWORD 文件大小低32位,PCTSTR 映射名称)
作用:创建文件映射内核对象
“文件”是上面创建的句柄;
“安全属性”是内核对象需要的,NULL表示使用系统默认的安全属性;“保护属性”是当将存储器提交给进程空间时,需要的页面属性:PAGE_READONLY, PAGE_READWRITE和PAGE_WRITECOPY。这个属性不能和文件对象的访问属性冲突。除了这三个外,还有两个属性可以和它们连接使用(|)。当更新文件内容时,不提供缓存,直接写入文件,可用SEC_NOCACHE;当文件是可执行文件时,系统会根据节赋予不同的页面属性,可用SEC_IMAGE。另外,SEC_RESERVE和SEC_COMMIT用于稀疏提交的文件映射,详细介绍请参考下文。
“文件大小高32位”和“文件大小低32位”联合起来告诉系统,这个映射所能支持的文件大小(操作系统支持264B文件大小);当这个值大于实际的文件大小时,系统会扩大文件到这个值,因为系统需要保证进程空间能完全被映射。值为0默认为文件的大小,这时候如果文件大小为0,创建失败。
“映射名称”是给用户标识此内核对象,供各进程共享,如果为NULL,则不能共享。
对象创建失败时返回NULL。
创建成功后,系统仍未为文件保留进程空间。
PVOID MAPViewOfFile(HANDLE 映射对象,DWORD访问属性,DWORD 偏移量高32位,DWORD 偏移量低32位,SIZE_T 字节数)
“映射对象”是前面建立的对象;
“访问属性”可以是下面的值:FILE_MAP_WRITE(读和写)、FILE_MAP_READ、FILE_MAP_ALL_ACCESS(读和写)、FILE_MAP_COPY。当使用FILE_MAP_COPY时,系统分配虚拟页文件,当有写操作时,系统会拷贝数据到这些页面,并赋予PAGE_READWRITE属性。
可以看到,每一步都需要设置这类属性,是为了可以多点控制,试想,如果在这一步想有多种不同的属性操作文件的不同部分,就比较有用。
“偏移高32位”和“偏移低32位”联合起来标识映射的开始字节(地址是分配粒度的倍数);
“字节数”指映射的字节数,默认0为到文件尾。
当你需要指定映射到哪里时,你可以使用:
PVOID MAPViewOfFile(HANDLE 映射对象,DWORD访问属性,DWORD 偏移量高32位,DWORD 偏移量低32位,SIZE_T 字节数,PVOID 基地址)
“基地址”是映射到进程空间的首地址,必须是分配粒度的倍数。
BOOL FlushViewOfFile(PVOID 进程空间地址,SIZE_T 字节数)
“进程空间地址”指的是需要更改的第一个字节地址,系统会变成页面的地址;
“字节数”,系统会变成页面大小的倍数。
写入磁盘后,函数返回,对于网络硬盘,如果希望写入网络硬盘后才返回的话,需要将FILE_FLAG_WRITE_THROUGH参数传给CreateFile。
当使用FILE_MAP_COPY建立映射时,由于对数据的更改只是对虚拟页文件的修改而不是硬盘文件的修改,当撤销映射时,会丢失所做的修改。如果要保存,怎么办?
你可以用FILE_MAP_WRITE建立另外一个映射,它映射到进程的另外一段空间;扫描第一个映射的PAGE_READWRITE页面(因为属性被更改),如果页面改变,用MoveMemory或其他拷贝函数将页面内容拷贝到第二次映射的空间里,然后再调用FlushViewOfFile。当然,你要记录哪个页面被更改。
BOOL UnmapViewOfFile(PVOID pvBaseAddress)
CloseHandle(HANDLE)
在不需要内核对象时,尽早将其释放,防止内存泄露。由于它们是内核对象,调用CloseHandle(HANDLE)就可以了。
在CreateFileMapping后马上关闭文件句柄;
在MapViewOfFile后马上关闭内存映射句柄;
最后再撤销映射。
内存映射文件的使用步骤
2.1 创建或打开一个文件
CreateFile
2.2 创建内存映射文件
HANDLE CreateFileMapping(
HANDLE hFile, //文件句柄
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
//安全属性
DWORD flProtect, //保护模式
DWORD dwMaximumSizeHigh,//大小的高32位
DWORD dwMaximumSizeLow, //大小的低32位
LPCTSTR lpName ); //文件映射内核对象的名称
2.3 映射成内存地址
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, //文件映射句柄
DWORD dwDesiredAccess, //访问模式
DWORD dwFileOffsetHigh, //地址偏移高32位
DWORD dwFileOffsetLow,//地址偏移低32位
DWORD dwNumberOfBytesToMap ); //要映射的字节数
2.4 使用内存
对于大文件,可以用多次映射的方法达到访问的目的。有点像AWE技术。
Windows只保证同一文件映射内核对象的多次映射的数据一致性,比如,当有两次映射同一对象到二个进程空间时,一个进程空间的数据改变后,另一个进程空间的数据也会跟着改变;不保证不同映射内核对象的多次映射的一致性。所以,使用文件映射时,最好在CreateFile时将共享模型设置为0独享,当然,对于只读文件没这个必要。
2.5 卸载映射
BOOL UnmapViewOfFile(
LPCVOID lpBaseAddress //卸载的地址
);
2.6 关闭内存映射文件
CloseHandle
2.7 文件关闭
CloseHandle
示例代码:
#include "stdafx.h"
#include "windows.h"void Map( )
{ //创建文件HANDLE hFile = CreateFile( "C:\\map.dat",GENERIC_READ|GENERIC_WRITE,0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL );//创建文件映射HANDLE hMap = CreateFileMapping( hFile, NULL,PAGE_READWRITE, 0, 1024 * 1024, NULL );//映射地址CHAR * pszText = (CHAR *)MapViewOfFile( hMap, FILE_MAP_ALL_ACCESS,0, 0, 1024 * 1024 );//使用内存strcpy( pszText, "Hello File Mapping" );printf( "%s\n", pszText );//卸载地址UnmapViewOfFile( pszText );//关闭文件映射CloseHandle( hMap );//关闭文件CloseHandle( hFile );
}int main(int argc, char* argv[])
{Map( );return 0;
}
使用windows内存-内存映射文件相关推荐
- 修改windows的主机映射文件(hosts文件)
修改windows的主机映射文件(hosts文件)可以用于xshell进行连接虚拟机时的ip地址,就不需要记住ip地址,而只需要记住主机名即可. 如果操作系统是window10,先拷贝出来,修改保存以 ...
- Boost.Interprocess.file_mapping内存映射文件
什么是内存映射文件? 文件映射是文件内容与进程地址空间的一部分的关联.系统创建一个文件映射关联文件和进程的地址空间.映射区域是进程用来访问文件内容的地址空间的一部分.一个文件映射可以有多个映射区域,以 ...
- windows笔记-内存映射文件
Windows提供了3种进行内存管理的方法: • 虚拟内存,最适合用来管理大型对象或结构数组. • 内存映射文件,最适合用来管理大型数据流(通常来自文件)以及在单个计算机上运行的多个进程之间共享数据. ...
- java 内存映射文件进程间通讯_[转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile...
进程间的通信方式有很多种, 上次我们说了最傻瓜的"共享外存/文件"的方法. 那么, 在本文中, 我们即将学习"共享内存"的方式实现进程间的通信, 这是IPC最快 ...
- Windows核心编程 第十七章 -内存映射文件(下)
17.3 使用内存映射文件 若要使用内存映射文件,必须执行下列操作步骤: 1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件. 2) 创建一个文件映射内核对象,告诉系统该 ...
- Windows核心编程 第十七章 -内存映射文件(上)
第1 7章 内存映射文件 对文件进行操作几乎是所有应用程序都必须进行的,并且这常常是人们争论的一个问题.应用程序究竟是应该打开文件,读取文件并关闭文件,还是打开文件,然后使用一种缓冲算法,从文件的各个 ...
- 《windows核心编程》 17章 内存映射文件
内存映射文件主要用于以下三种情况: 系统使用内存映射文件载入并运行exe和dll,这大量节省了页交换文件的空间以及应用程序的启动时间 开发人员可以使用内存映射文件来访问磁盘上的数据文件.这使得我们可以 ...
- 内存映射文件——Windows核心编程学习手札之十七
内存映射文件 --Windows核心编程学习手札之十七 与虚拟内存一样,内存映射文件保留地址空间,并将物理存储器提交给该区域,差别在于所提交的物理存储器是磁盘上有文件存在的空间,而非系统的页文件,一旦 ...
- 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
本文背景: 在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用:根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制. 本 ...
- Windows之内存映射文件
=====================Windows之内存映射文件===================== 几乎每个应用程序都要处理文件,但要处理好并不容易.应用程序到底是先应该打开文件.再读取 ...
最新文章
- MongoDB使用小结:一些常用操作分享
- java采集温湿度水浸_配电室水浸及温湿度监测系统可加强环境保障
- 看完这篇文章你还敢说你懂JVM吗?
- Oracle入门(二)之服务启动bat
- navigator.geolocation的应用 - 将定位信息显示在百度地图上
- html设置表格和div的距离,CSS/HTML Div调整大小和表格定位
- [Err] 1231 - Variable 'sql_mode' can't be set to the value of 'NULL
- 设计模式之单例模式8种实现方式,其三:懒汉式(线程不安全)
- Microsoft Dynamics 365 之 味全食品 项目分享和Customer Engagement新特性分享
- java 删除指定文件夹和下面所有文件_JAVA语言基础
- H264 STAP-A解包代码(测试通过)
- Vmware15虚拟机安装win7镜像
- 排队论模型及MATLAB实现
- 【R语言】结巴分词与词性提取(以“提取知乎问题标题的频繁词前100个形容词”实战为例)(3月25日学习笔记)
- 如何用js实现数组倒序输出
- Python用socket、多线程实现一对一聊天室
- c语言分段函数x2-sinx,大学高等数学: 第二章第五讲三种分段函数求导法, 再也不担心了...
- c语言实现简单的24点游戏
- Python绘制3D图形:Axes3D
- git使用meld的方法