`
Dustin
  • 浏览: 314846 次
  • 性别: Icon_minigender_1
  • 来自: 广州/成都
社区版块
存档分类
最新评论

File Mapping析疑

阅读更多
    最初接触File Mapping是为了能够方便地处理一个几百兆的大文件,当时查了些资料大概了解了一下就匆匆动手了,因为知其然而不知其所以然,在使用过程中遇到了不少问题,今天在这里就是想把这些历史遗留问题解决掉。

    问题一、Mapping有“映射”之意,那么在该语境中形成映射关系的双方是谁,也就是从哪里映射到哪里呢?
    要回答这个问题,我们必须要对虚拟内存有所了解。现在操作系统中,大多都使用虚拟内存技术来对内存进行管理。通过虚拟内存,操作系统给予了每个进程一个统一的地址空间。在32位操作系统中,该地址空间的大小达到 2^32个,也就是4G了。从一个进程的角度看来,这4G的地址空间是自己独享的,也就是说,如果操作系统允许的话,我可以访问这4G地址空间中的任何一个。当然,操作系统是不可能让一个进程随心所欲地使用这些地址的。下面,我们来看看这些地址具体是怎样分配的:

     上面这个图大家应该都很熟悉,它是Linux中进程的内存映象。我们可以看到,在4G的地址空间中,我们先从下往上看, 0~0x08047ffff(大概128M左右)是系统保留的,不能使用。read-only segment和read/write segment用以存放系统加载器从可执行文件中载入的代码段以及数据段等内容。运行时堆大家应该都比较清楚,是动态分配内存的地方,我们通过malloc和free等函数动态在堆中分配和释放内存,堆的大小是往上增长的,最大可达到0x3FFFFFFF处。好,到这里我们在从上往下看,0xc0000000以上是核心虚拟内存,专门为操作系统核心的数据结构以及代码预留的,一般用户进程无权使用。然后就到了栈区了,这里是系统保存跟函数操作有关的数据,如局部变量,函数参数等内容。与堆不一样,栈是从上往下增长的,其栈顶通过寄存器esp指出。那么被堆和栈夹着的区域是干什么的呢?原来,那是用来放动态共享库的。动态共享库是在程序被载入时或者运行过程中载入到进程内存空间中的,它存放的地方就是我们称作内存映射区的这个地方。
    这样一看,原来进程开始运行时,4G的地址已经被用掉了不少,其中,光是操作系统所占用的核心虚拟内存就达到1G,加上程序的代码和数据以及动态共享库等等,我们大概就剩下2G左右的地址空间可以使用了。那么,这2G空间我们是如何使用的呢?第一,我们使用malloc函数,在堆中分配空间,使堆往上增长;第二,我们在函数中使用局部的数据,以及函数调用时现场的保留,使栈空间往下增长;第三,我们使用File Mapping,使内存映射区往上增长。
    好了,终于出现File Mapping 了。现在,我们也可以知道题目中“映射”的其中一方了:内存。原来它就是在内存映射区中的一段地址空间。那么,“映射”的另一方又是什么呢?那自然是文件了。我们可以将任何类型任何大小(只要操作系统支持,现在win32支持最大的文件为16EB,就是2^64)的文件映射到内存映射区中。当然,太大的文件我们不可能一次性把它全部映射到虚拟内存中去,毕竟我们大概只有2G的地址空间,两者间是不可能构成一一对应的关系的。此时,我们可以将文件分段进行映射,每次将文件的一部分映射到内存空间中。映射完以后,我们就可以像访问内存那样直接访问文件了。

    问题二、数据在哪呢?数据文件?物理内存?页面文件?
    这里,我们暂且将被映射的文件称为数据文件。当我们映射好一个数据文件以后,操作系统并不会马上将文件中的内容提交到物理内存中去,数据还是原封不动地放在数据文件中。但是,当程序首次对文件中某个数据进行访问时(read /write),操作系统就会将该数据从数据文件中调入物理内存中,供CPU使用。操作完毕后,当我们解除映射时,操作系统将根据映射的属性(write/write-on-copy)决定是将更改后的数据写回到数据文件中还是将更改直接丢弃。Readonly 不存在这个问题,因为不可能被更改,因此unmap时只需将内存中的数据丢弃就可以了。
     这中间还有一个问题,那就是在映射以后和解除映射之前这个时间段内,物理内存中的数据是有可能被换出的(swap out),那么,换出时这些数据是被存放在数据文件中还是像一般数据那样存放在系统的页面文件中呢?同样,这也是跟映射的属性紧密相关的:
    如果映射为readonly,那么换出时只需修改相应的页表(page table)内容,标注其已被换出即可。
    如果映射为write-on-copy,那么换出将存放在页面文件中,
    如果映射为write,那么换出时将写会到数据文件中。
      
    问题三、使用File Mapping为什么可以提高访问文件的速度呢?
     这是因为操作系统在处理一般读写跟处理内存映射使用的方法不一样。在处理一般的读写操作时,操作系统一般使用中断的方式,先将内容拷贝到核心虚拟内存缓冲,然后再拷贝到进程空间中;但是,处理内存映射文件时,一般使用虚拟内存管理器,无需进行中间的拷贝过程,因此速度加快。此外,像Windows这样使用页式管理虚拟内存的操作系统中,数据的换入换出都是以页为单位的(通常是4k或者8k),因为程序一般都具有时间和空间的局部性(locality),因此,相当于进行了大量的缓冲操作,有利于提高性能。

    问题四、什么情况适合使用 File Mapping呢?看看人家的建议:
           File mapping is effective in the following situations:

         You should not use file mapping in the following situations:

  • You want to read a file sequentially from start to finish only once.

  • The file is several hundred megabytes or more in size. (Mapping large files fills virtual memory space quickly. In addition, your program may not have the available space if it has been running for a while or its memory space is fragmented.)


    问题五、为什么在操作大文件时速度变得很慢呢?
    遇到这个问题,你可以首先打开Windows的任务管理器,看看你进程究竟使用了多少的内存。呵呵,通常都是个天文数字。占用了那么多的内存,系统肯定就很慢了。遇到这样的问题,我们通常都是使用内存映射文件对数据文件进行遍历操作,譬如像将A文件拷贝为B文件。上面我们提到,操作系统是在真正用到数据的时候才会把它从数据文件中提交到物理内存里面的,因此,刚做好映射不进行操作的话,进程并不会消耗多少内存。但是,一旦你开始进行遍历,那么,操作系统就马上将它们调入物理内存中(你可以看看页面错误的数量,肯定是飞速增长的),于是,内存就一路飞涨了。
    怎么办呢?不要一次性把整个文件进行映射,而是分开进行,操作完一部分后,将它unmap掉,这样,操作系统就会把它们“赶回家去”了,内存就不会占用太高了。

Reference:
[1] Computer Systems:A Programmer's Perspective ,Chapter 10 Virtual Memory 
[2]
Memory Management
[3]Virtual Memory and Memory Mapping
[4] Mapping Files Into Memory

分享到:
评论
20 楼 iunknown 2007-01-20  
七猫 写道
实际操作中file mapping在数据commit上我个人认为除了我说的节省调用和COPY的时间,其他并没有做太多的优化。


mmap 语法如下:

paddr = mmap( addr, len, prot, flags, fd, offset );
mmap 建立由 fd 代表的文件字节范围 [offset, offset + len) 到调用进程地址范围 [paddr, paddr + len] 上的映射。 flags 指定映射类型,可以是 MAP_SHARED 或 MAP_PRIVATE。

一个进程可以建立两种不同类型的文件映射 -- 共享和私有。当进程写页面的时候,对于共享映射,直接修改被映射的对象。内核直接修改页面的共享副本,然后在刷新页面时将它们写回磁盘上的文件。如果映射是私有的,任何修改动作都会生成页面的一个副本,然后仅修改该页面。这样写操作不会修改相应的对象,即内核在刷新页面时不会将修改写回文件。
19 楼 Arath 2007-01-19  
喔?哈哈,可能说得不够清楚,多交流就好
18 楼 七猫 2007-01-19  
跟你沟通真是难啊。
17 楼 Arath 2007-01-19  
windows系统有一个实现就是将所有的IO操作都统一为stream的形式,所以一套file的函数既可以用来访问文件还可以用来操作控制台、管道、串口等设备,封装的这么统一势必造成性能的下降,其中很多应该都需要增加新的异步操作,如果file mapping只针对文件操作,那么异步操作少了,经过的途径短了,应该会快很多.
我所提的cache不是你所指的读写cache, 实际就相当于将所需要访问的数据多读一些到内存,这样访问不就提高了?
拿MSDN中的一段描述吧:
File mapping allows a process to access files more quickly and easily by using a pointer to a file view. Using a pointer improves efficiency because the file resides on disk, but the file view resides in memory. File mapping allows the process to use both random input and output (I/O) and sequential I/O. It also allows the process to efficiently work with a large data file, such as a database, without having to map the whole file into memory. When the process needs data from a portion of the file other than what is in the current file view, it can unmap the current file view, then create a new file view.

16 楼 七猫 2007-01-19  
//file mapping所带来的性能提升主要还是在cache的机制?

你的证明在哪里呢?我印像中filemapping并没有比ReadFile,WriteFile更多的cache.
15 楼 七猫 2007-01-19  
非异步方式写?在WIN下可能吗?win内核应该是全异步操作的。(这是跟linux最大的不同吧)

这块比较复杂,在有本讲WIN操作系统的书里有提到,WriteFile和FileMap的写调用的接口应该都是一样的,他们的写都是交给IO管理器去做的。
至于文件系统什么时候去写,这个是比较复杂的算法。
你真的想看原码的话,可以看nt4的ntfs驱动原码和ntos里的mm目录,cache目录,io目录。
14 楼 Arath 2007-01-19  
七猫 写道
至于读写隔离,我不知道这是啥意思?跟题目又有啥关系。
实际操作中file mapping在数据commit上我个人认为除了我说的节省调用和COPY的时间,其他并没有做太多的优化。至少我印像中没有看过类似的资料来证实这一点。
关于这些,我想那本nt的文件系统的书里面的cache管理器里面可能会提到。
writefile跟fwrite不一样的地方就是fwrite内部有cache,但writefile(或者是linux下的write)也并不是立即写硬盘,这个要看操作系统的实现。
关于这些可以说很多。有空多研讨研讨也不错。


我指的读写隔离意思是你不能将file mapping只看作文件的映射,而将读写操作隔离开考虑,他们应该是一个整体构成file mapping对文件的操作.
上面我回了一个,其实组要还在于操作系统对不同函数的实现方法和所实现的功能所在的层位,差距是无可避免的.
这里你倒是提醒了我,write file的机制实际上异步的,如果file mapping采用非异步的方式去写,那样的话速度应该会快很多,当然这也是猜测.
也许要拿windows的源码来看看会比较了解
13 楼 Arath 2007-01-19  
差距是一定有的.
对于这个差距,作为未知的一面,我猜测应该是操作系统内部对file mapping的文件读写与普通的文件读写API有差距,这一点可以从windows的GDI API和DirectX的差距可以推想,GDI API和DirectX其底层是一样的.
另一个方面就是有关Cache的算法,测试程序没有任何优化的算法,所以性能上有差距这一点是肯定的.
我不是说不用file mapping,而只是说明大文件操作非file mapping不能胜任的说法至少是不完全的. 同时也是要说明file mapping所带来的性能提升主要还是在cache的机制.
最后有关将两个测试颠倒,这一点测试的误差不大,因为文件操作越大,那么硬件和操作系统的cache机制就会影响越小,实际也是如此.
12 楼 七猫 2007-01-19  
至于读写隔离,我不知道这是啥意思?跟题目又有啥关系。
实际操作中file mapping在数据commit上我个人认为除了我说的节省调用和COPY的时间,其他并没有做太多的优化。至少我印像中没有看过类似的资料来证实这一点。
关于这些,我想那本nt的文件系统的书里面的cache管理器里面可能会提到。
writefile跟fwrite不一样的地方就是fwrite内部有cache,但writefile(或者是linux下的write)也并不是立即写硬盘,这个要看操作系统的实现。
关于这些可以说很多。有空多研讨研讨也不错。
11 楼 七猫 2007-01-19  
而且你看看你前面的发言:为什么filemap推荐使用,因为他的cache好,但你似乎又想证明,不用filemap,你自己写cache也可以。
10 楼 七猫 2007-01-19  
Arath 写道
自己做了一个测试
http://www.iteye.com/topic/48412

file mapping不能将读写隔离吧;)




老兄,你的第三种方法只是一次性的把文件从内存读进来,一次性的写进去吧。Write: 4166
Test3:
Access: 922
Write: 4887

access的差不多,write差20%,你觉得还是在同一级别上?(我甚至觉得access用缺页中断应该还慢些,因为一次性读入的话可能效率会更高,分多次缺页中断可能速度会慢些,我怀疑可能是内存COPY的时间把这个时间搞淡了。

BTW:你把FileOperation3,FileOperation1调个次序执行,没准时间会不一样的。
9 楼 Dustin 2007-01-19  
引用
最初接触File Mapping是为了能够方便地处理一个几百兆的大文件

  只是为了说明我接触File Mapping的原因,并不是说FileMapping只能用于处理大文件

使用File Mapping处理文件有两个好处:
  1、文件快速访问。普通的文件读写使用系统调用(read,write)数据先从磁盘拷贝到内核空间,再从内核空间拷贝到用户进程空间,这个模型在《Unix环境高级编程》中有详细描述的。File Mapping采用虚拟内存管理机制来处理文件读写,不需要中间的拷贝过程,因此效率要比普通的文件读写要快。
  2、简单高效。File Mapping由OS管理同步和缓冲,将文件映射成用户进程中的一维地址空间,因此用户可以像使用数组那样使用文件,很多库函数得以重用。

PS:google "memory mapping"得到的资料好像要多一些


8 楼 Arath 2007-01-18  
自己做了一个测试
http://www.iteye.com/topic/48412

file mapping不能将读写隔离吧;)
7 楼 七猫 2007-01-18  
filemap才是影射,
read,write是COPY+中断调用(或者是sysenter)。
6 楼 七猫 2007-01-18  
我只说LINUX系统下的我的理解
mmap打开时,OS并不把所有的文件内容都读到内核空间去。
进程调用mmap()时,只是在进程空间内新增了一块相应大小的缓冲区,并设置了相应的访问标识,但并没有建立进程空间到物理页面的映射。文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。因此,第一次访问该空间时,会引发一个缺页异常。在这个时候才会去读物理文件。

这里面的cache就是vfs下层的cache,并没有另外的cache,除非你自己编程写cache,跟read,write里用的系统cache似乎并没有太大的差别。

大文件的效率因为文件大,内核->用户的COPY会很多(LINUX下有函数名字好像就叫copy_to_user,copy_to_kernel),这种做法跟sendfile,TransmitFile这种直接内核COPY的想法是一样的。
5 楼 Arath 2007-01-18  
对了上图中Physical memory->Process Virtual Memory绝对不是拷贝,只是影射!
4 楼 Arath 2007-01-18  
文件访问速度的瓶颈在于磁盘访问速度的相对低下,filemapping的优势主要就在于用户自控制的cache方式.
而且也不存在什么系统空间到用户空间的copy问题,保护模式是物理内存与地址脱离的.
以下是filemapping的工作图,其中主要体现了file mapping作为share memory的形成:
3 楼 七猫 2007-01-18  
Arath 写道
File Mapping有两个好处:
1. 共享内存
在保护模式下,File Mapping是最基本的跨进程共享数据的方法,通过使用相同名字的file mapping就可以使多个进程使用同一块内存区,得到相同的数据. 这一点完全基于CPU的保护模式运行机理.
2. 提高文件访问速度
实际上这个提速原理就是cache, file mapping根据需求是将文件数据大量读到了内存中,速度自然快,特别适合那些需要不停的随机或跳转访问文件的程序,速度得以大幅提高.
这一点文中的解释是错误的,无论file mapping还是直接的文件操作,其访问文件的途径和方法都是一样,所谓的页读取在普通的文件访问中也是一样存在的,只是物理的页因为系统的多任务性以及应用的更大需求而往往会被新的页覆盖,或则下一次的访问超过了物理页cache的范围需要重新读取,从而导致多次的寻道读取,这一点硬盘的cache的机理就可以明白.简单说就是利用操作系统来做了一个大的硬盘cache.
至于一定要用file mapping来解决大文件,其实完全没有太大的意义. 明白了file mapping的原理,如果单纯只是为了操作大文件,那么你完全可以自己去allocate buffer,然后作交换访问,当然这样你要多写很多代码,所以才有人推荐file mapping访问大文件,而并非file mapping就是用来访问大文件的.
我觉得原文中的解释似乎是对的。

映射文件可以把系统中的内存直接映射到你的用户空间中去,好像是由缺页中断还是什么来控制什么时候从真实的文件中读入,他不是从系统空间复制到用户空间,因此少了系统中断调用的时间以及内存COPY的时间。跟cache根本没关系。特别是大文件的读写这样很有效率。filemap并没有将文件大量读到内存中去。
2 楼 Arath 2007-01-17  
File Mapping有两个好处:
1. 共享内存
在保护模式下,File Mapping是最基本的跨进程共享数据的方法,通过使用相同名字的file mapping就可以使多个进程使用同一块内存区,得到相同的数据. 这一点完全基于CPU的保护模式运行机理.
2. 提高文件访问速度
实际上这个提速原理就是cache, file mapping根据需求是将文件数据大量读到了内存中,速度自然快,特别适合那些需要不停的随机或跳转访问文件的程序,速度得以大幅提高.
这一点文中的解释是错误的,无论file mapping还是直接的文件操作,其访问文件的途径和方法都是一样,所谓的页读取在普通的文件访问中也是一样存在的,只是物理的页因为系统的多任务性以及应用的更大需求而往往会被新的页覆盖,或则下一次的访问超过了物理页cache的范围需要重新读取,从而导致多次的寻道读取,这一点硬盘的cache的机理就可以明白.简单说就是利用操作系统来做了一个大的硬盘cache.
至于一定要用file mapping来解决大文件,其实完全没有太大的意义. 明白了file mapping的原理,如果单纯只是为了操作大文件,那么你完全可以自己去allocate buffer,然后作交换访问,当然这样你要多写很多代码,所以才有人推荐file mapping访问大文件,而并非file mapping就是用来访问大文件的.
1 楼 cookoo 2007-01-16  
图片看不到哩

相关推荐

    FileMapping进程中相互通讯例子

    在这个“FileMapping进程中相互通讯例子”中,我们将探讨如何利用FileMapping技术实现两个不同进程间的通信。 1. **文件映射基础**: - **创建文件映射对象**:使用`CreateFileMapping()`函数创建一个文件映射对象...

    windows FileMapping 共享内存用法 编译通过 测试通过 附件是sln工程

    在Windows操作系统中,`FileMapping`是一个非常重要的内存管理机制,它允许不同的进程之间共享同一块内存区域。这种技术在多进程通信、数据同步以及高效数据交换等方面具有广泛的应用。以下将详细介绍`FileMapping`...

    Window-file-mapping.rar_Mapping File_file mapping_内存映射文件_文件共享_鍐呭

    内存映射文件(Memory-Mapped File)是一种在Windows操作系统中实现进程间通信(IPC, Inter-Process Communication)的有效方式,它允许多个进程共享同一块内存区域,从而实现数据的高效交换。这一技术常用于需要...

    IIS下Zend 出现 Unable to view file mapping 问题的解决方法汇总

    zend 错误日志中有:Unable to view file mapping, 试图访问无效的地址。网上搜了下解决方法有 解决方法如下: 对比php两个版本的php.ini文件。 ;extension=php_yaz.dll;extension=php_zip.dll检查这个两个是否存在...

    Mapping file的使用

    为了解决这些问题,Cadence Virtuoso 使用了映射文件(mapping file),特别是四种类型的映射文件:Cell name mapping file、Layer name mapping file 和 Text font mapping file。 1. Cell name mapping file: ...

    solidity入门学习——mapping

    一、solidity中,映射的关键字为mapping,首先我们先来定义两个mapping, mapping(address =>uint) idmapping和mapping(uint =>string) namemapping。idmapping用来表示地址变量和整型变量的对应关系,在注册过程中...

    MemoryMappingFile

    内存映射文件(Memory-Mapped File)是一种在操作系统层面实现高效数据共享的技术,尤其适用于多进程间的通信。在Win32环境下,它通过将文件直接映射到进程的虚拟地址空间来实现,允许进程直接读写文件内容,而无需...

    SAP PI Java Mapping com.sap.aii.mapping.api PI MAPPING开发必须jar包

    在SAP Process Integration (PI) 中,Java Mapping是一种强大的工具,用于处理和转换数据流,以确保不同系统间的数据交换准确无误。标题提到的"com.sap.aii.mapping.api PI MAPPING开发必须jar包"是Java Mapping开发...

    CreateFileMapping的使用

    _tprintf(_T("Failed to create file mapping object.\n")); CloseHandle(hFile); return 1; } CloseHandle(hMapFile); CloseHandle(hFile); return 0; } ``` #### 六、总结 `CreateFileMapping` 是一种...

    mybatis的Mapping接口和配置文件自动生成

    在开发过程中,手动编写Mapper接口和对应的XML配置文件是一项繁琐的工作,而“mybatis的Mapping接口和配置文件自动生成”工具则能有效地解决这个问题,极大地提高了开发效率。 该工具的核心功能是基于SQL Server...

    matlab_mapping_toolbox

    《MATLAB Mapping Toolbox详解》 MATLAB Mapping Toolbox是MATLAB软件环境中的一个重要工具箱,专为地球科学、航空航天、地理信息系统(GIS)以及导航领域的研究人员和工程师设计。它提供了丰富的函数和工具,用于...

    端口转换软件tcpmapping

    端口转换软件TcpMapping是一款非常实用的工具,主要用于网络中的端口映射或者称为端口转发。在深入了解TcpMapping之前,我们首先需要理解什么是端口和端口转换。 端口在计算机网络中扮演着重要的角色,它们是网络...

    使用FMode 提取黑神话悟空模型Mapping文件

    使用FMode 提取黑神话悟空模型Mapping文件

    SANGFOR_NGAF_6.8_DNS-Mapping配置指导.pdf

    SANGFOR NGAF 6.8 DNS-Mapping 配置指导 SANGFOR NGAF 6.8 DNS-Mapping 配置指导是深信服公司发布的一份关于 NGAF 6.8 version 的 DNS-Mapping 配置指南。下面是从该指导中总结的重要知识点: 1. 文档说明:文档...

    com.sap.aii.mapping.api PI MAPPING开发必须jar包

    XI PI MAPPING开发必须jar包 import com.sap.aii.mapping.api.*; import com.sap.aii.mapping.api.*; import com.sap.aii.mapping.lookup.*; import com.sap.aii.mappingtool.tf7.rt.*;

    matlab-mapping toolbox-提取自r2019b

    《MATLAB Mapping Toolbox详解——基于R2019b版本》 MATLAB Mapping Toolbox是MATLAB软件中的一个重要扩展工具箱,专为地球科学、航空航天、地理信息系统(GIS)以及地图制图领域的用户设计。该工具箱包含了丰富的...

    Windows下的多进程间通信及数据共享

    FileMapping对象是Windows操作系统中一种特殊的内核对象,它可以将一个文件映射到进程的虚拟地址空间中,从而实现多个进程之间的数据共享。 创建一个FileMapping对象可以使用CreateFileMapping函数,该函数将创建一...

    arcgis10.3.1的ESRI Producting Mapping扩展

    arcgis103.1版本插入动态表格,制图时插入动态表格,Esri Mapping and Charting Solutions。

    excel导入mapping设置

    excel导入mapping设置

Global site tag (gtag.js) - Google Analytics