文件内存映射(一):它是什么

作者:pany young
链接:http://www.lofter.com/lpost/1fea4630_12e51440b
来源:LOFTER
最近在开发某个功能的时候考虑到要把数据持久化到硬盘上.在综合考虑各方面的因素后,在技术选择上选择了 -- 《文件内存映射》。所以接下来想用几部分来介绍这个技术。
一.它是一种文件操作的方式,由操作系统支持
有人可能会觉得上一句的后半部分有点废话,但我觉得却是必须的,因为每个操作系统都有不同的文件操作方式,例如Win32 API和MFC提供多种函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。不一定操作系统就支持内存映射,所以前提是所用的操作系统支持这功能。无论是C++还是Java,亦然如此。
然后这个技术优点是当需要操作一些大文件的时候,它的效率比其他的文件操作方式更高,能很高效的处理大文件。
二.它与虚拟内存的区别
二者的联系
虚拟内存和内存映射文件都是将一部分内容加载到,另一部分放在磁盘上的一种机制,二者都是应用程序动态性的基础,由于二者的虚拟性,对于用户都是透明的.
虚拟内存其实就是硬盘的一部分,是计算机RAM与硬盘的数据交换区,因为实际的物理内存可能远小于进程的地址空间,这就需要把内存中暂时不用到的数据放到硬盘上一个特殊的地方,当请求的数据不在内存中时,系统产生却页中断,内存管理器便将对应的内存页重新从硬盘调入物理内存。
内存映射文件是由一个文件到一块内存的映射,使应用程序可以通过内存指针对磁盘上的文件进行访问,其过程就如同对加载了文件的内存的访问,因此内存文件映射非常适合于用来管理大文件。
二者的区别
1.虚拟内存使用硬盘只能是页面文件,而内存映射使用的磁盘部分可以是任何磁盘文件.
2.二者的架构不同,或者是说应用的场景不同,虚拟内存是架构在物理内存之上,其引入是因为实际的物理内存运行程序所需的空间,即使现在计算机中的物理内存越来越大,程序的尺寸也在增长。将所有运行着的程序全部加载到内存中不经济也非常不现实。内存映射文件架构在程序的地址空间之上,32位机地址空间只有4G,而某些大文件的尺寸可要要远超出这个值,因此,用地址空间中的某段应用文件中的一部分可解决处理大文件的问题,在32中,使用内存映射文件可以处理2的64次(64EB)大小的文件.原因内存映射文件,除了处理大文件,还可用作进程间通信。

三.原理
“映射”就是建立一种对应关系,在这里主要是指硬盘上文件的位置与进程逻辑地址空间中一块相同区域之间一一对应,这种关系纯属是逻辑上的概念,物理上是不存在的,原因是进程的逻辑地址空间本身就是不存在的,在内存映射过程中,并没有实际的数据拷贝,文件没有被载入内存,只是逻辑上放入了内存,具体到代码,就是建立并初始化了相关的数据结构,这个过程有系统调用mmap()实现,所以映射的效率很高.

               内存映射原理
上面说到建立内存映射没有进行实际的数据拷贝,那么进行进程又怎么能最终通过内存操作访问到硬盘上的文件呢?
看上图:
1.调用mmap(),相当于要给进行内存映射的文件分配了虚拟内存,它会返回一个指针ptr,这个ptr所指向的是一个逻辑地址,要操作其中的数据,必须通过MMU将逻辑地址转换成物理地址,如图1中过程2所示。
2.建立内存映射并没有实际拷贝数据,这时,MMU在地址映射表中是无法找到与ptr相对应的物理地址的,也就是MMU失败,将产生一个缺页中断,缺 页中断的中断响应函数会在swap中寻找相对应的页面,如果找不到(也就是该文件从来没有被读入内存的情况),则会通过mmap()建立的映射关系,从硬 盘上将文件读取到物理内存中,如图1中过程3所示。
3.如果在拷贝数据时,发现物理内存不够用,则会通过虚拟内存机制(swap)将暂时不用的物理页面交换到硬盘上,如图1中过程4所示。
四.它的其他功能:
例如进程之间的通信。

参考:
https://blog.csdn.net/zzq060143/article/details/54619571
https://blog.csdn.net/whoamiyang/article/details/53365385
https://blog.csdn.net/mengxingyuanlove/article/details/50986092

你可能感兴趣的:(文件内存映射(一):它是什么)