一、为什么需要内存映射
“内存映射文件”
可以将硬盘上的文件映射到虚拟地址空间
,这样就不需要将所有东西都放入到页交换文件中,比如系统有许多程序同时运行时,如果将这些程序文件都加载到页交换文件中,页交换文件
将会变得非常大。事实上,Windows 也并没有将硬盘上的程序文件复制到页交换文件
中,因为这样不仅会让页交换文件
将会变得非常大,也会浪费很多时间,特别是可执行程序非常大的时候。
当用户要求执行一个应用程序时,系统会打开该应用程序的.exe
文件,并计算出应用程序的代码和数据的大小,然后系统会在进程的虚拟地址空间预定一块地址空间,并注明与该区域相关联的物理存储器就是.exe
文件本身。
当把一个位于硬盘上的文件(可以是.exe
,.dll
也可以是普通文件)映像用作地址空间区域对应的物理存储器时,我们称这个文件映像为“内存映射文件”
。
现在我们可以对Windows内存体系(2)--虚拟内存第 2 节的图进行完善了,加入“内存映射文件”部分:
二、内存映射文件技术介绍
常用的有 Win32 API 的CreateFile()
、WriteFile()
、ReadFile()
和 MFC 提供的CFile
类都可以实现文件的读写操作。一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十 GB、几百 GB、乃至几 TB 的海量存储,此时在以平常的文件处理方法进行处理显然是行不通的(效率低下,而且内存没那么大)。目前,对于这种大文件的操作一般是以内存映射文件的方式来加以处理的。
内存映射文件也是 Windows 的一种内存管理方法,提供了一个统一的内存管理特征,使应用程序可以通过内存指针对磁盘上的文件进行访问。通过文件映射将磁盘文件内容(全部或者部分)与进程虚拟地址空间的某个区域建立映射关联,可以直接对被映射的文件进行访问,而不必执行文件 I/O 操作也无需对文件内容进行缓冲处理。内存文件映射的这种特性是非常适合于用来管理大尺寸文件的。
三、大文件读写实例
通过 C++调用系统 API 实现文件映射的步骤大致如下:
本示例首先在D:\
生成一个大小为 1GB 的BigFile.data
文件,然后使用内存映射技术将该文件内全部填充字符 A,随后读取其中的第20000~20100字节
,并将这些字节修改为字符 B,然后再次读取已验证是否修改成功。
1 |
|
文章图片带有“CSDN”水印的说明:
由于该文章和图片最初发表在我的CSDN 博客中,因此图片被 CSDN 自动添加了水印。