第一章:源起 

遇到一个问题,如果一个客户数据文件有2g大,客户要通过界面查询文件中的数据并用列表控件显示数据,要怎么处理这个文件才能让应用程序不会长时间无响应,客户感觉不到程序的卡顿?

第二章:解决之道

第一反应是用内存映射文件处理大文件,将文件分成数次映射至内存地址空间,避免一次性缓冲整个文件带来的界面长时间无响应,并将暂时不用的内存映射文件取消映射,客户是用列表控件进行显示,那就可以在首次加载的时候只加载第一页的内容就进行显示,之后在缓冲下一页的内容,当用户查看中间页面的内容时可以缓冲将当前页面的上下页面和首页、最后页面对应的文件加载至进程地址空间中,其他的文件映射视图取消映射。

进一步完善创建多线程处理,主线程创建文件映射内核对象,多个子线程分别映射磁盘文件的一部分至进程地址空间并进行数据分析,处理完数据的线程通过SendMessage或者PostMessage又或者锁、关键段、内核线程同步方式等通知界面线程,而界面线程再做一些NOT WAIT操作,添加两个进度条提示首页加载进度和整体文件加载进度,首页加载完成时隐藏进度条并显示数据。

      第三章:正文

      3A:内存映射文件介绍:

创建内存映射文件相当于先调拨一块地址空间区域,然后给区域调拨物理存储器。不同之处在于内存映射文件的物理存储器来自于磁盘上的文件,而不是从系统的页交换文件中分配的。

  3B:内存映射文件主要用于以下三种情况:

1.系统使用内存映射文件来载入并运行.exe和动态链接库(.dll)文件,可以节省页交换文件的空间和应用程序启动的时间。

2.开发人员可以用内存映射文件来访问磁盘上的数据文件,使得我们可以避免直接对文件进行IO操作和对文件内容进行缓存。

3.通过内存映射文件,我们可以在同一台机器的不同进程之间共享数据,windows也提供了其他一些方式来在进程间传送数据,但这些方法都是通过内存映射文件包装而成,因此最快的同一台机器上的进程间共享数据方法就是内存映射文件。

3C:常用API

CreateFile:打开文件内核对象

CreateFileMapping:创建一个指定名称的文件映射内核对象,通过参数指定映射到进程地址空间的文件句柄。

OpenFileMapping:打开一个指定名称的文件映射内核对象。

MapViewOfFile:把文件数据映射到进程地址空间,通过参数指定映射到进程地址空间的文件映射句柄和文件访问方式。

FlushViewOfFile:处于速度上的考虑,系统会对文件数据的页面进行缓存处理,这样在处理文件映射视图时就不需要随时更新磁盘上的文件,调用FlushViewOfFile将文件映象的修改立即从高速缓存写入磁盘映象。

对内存映射文件的处理类似读取到内存中的文件,或者理解成操作一串字符串。

UnMapViewOfFile:完成文件数据映象的释放。

CloseHandle,关闭文件映射内核对象,关闭文件内核对象,要调用两次。

 3D:注意事项:

可以对同一个文件创建多个内存映射文件,但系统并不保证多个内存映射文件之间的数据一致性,系统只保证同一个内存映射文件的多个视图数据一致。

用作内存映射文件的磁盘文件最好是只读属性,可以避免其他进程对文件修改二造成的映射文件和磁盘文件的不一致,如果无法确认文件是只读的,那么在创建文件对象的CreateFile时指定访问权限为独占。

不应该用内存映射文件来跨网络共享可写文件,系统无法知晓网络上另外一台电脑对文件的操作而继续使用内存中的原始数据。

内存映射文件不一定需要磁盘文件,也可以创建以页交换文件为后备存储器的内存映射文件。与创建以磁盘文件为物理存储器的内存映射文件不同的步骤是:不需CreateFile步骤,在CreateFileMapping时文件内核对象传参INVALID_HANDLE_VALUE,这就告诉系统物理存储设备从页交换文件分配而不是磁盘文件。

    第四章:补充话题:

    4A:稀疏调拨的内存映射文件

之前的内存映射文件要么从磁盘上的数据文件中调拨,要么从页交换文件中调拨,这意味着对存储器的使用可能并不如我们希望的那么高效。按照jeffrey大神的例子,有一个电子表格文件定义:

CELLDATA CellData[200][256];如果CELLDATA的大小是128字节,那么这个数组就需要6553600字节的物理存储器,这也就表示程序开始运行就需要从页交换文件中分配大量的物理存储器,但是用户通常只用前面几个单元格存放信息,绝大多数的单元格都是浪费的。

我们希望把电子表格作为文件映射对象来共享,但又不想一开始就分配这么大的物理存储器,但是采用文件分片映射视图的方式编程会很繁琐,此时我们可以采用稀疏文件映射方式。

稀疏调拨的内存映射文件方法:

CreateFileMapping的fdwProtect参数中指定SEC_RESERVE或SEC_COMMIT,这两个标记只有在以页交换文件为后备存储器来创建文件映射对象时才有意义,SEC_COMMIT标志让CreateFileMapping从页交换文件中调拨存储器。

如果在调用CreateFileMapping的时候传入SEC_RESERVE标志,那么系统不会从页交换文件中调拨屋里存储器,它只返回文件映射对象的句柄。

MapViewOfFile给指定的文件映射对象创建一个视图,即预定一块地址空间区域,但不会给该区域调拨任何物理存储器,此时访问该区域的操作都是非法的。

调用VirtualAlloc给共享区域调拨物理存储器,我们可以只调拨部分存储器给MapViewOfFile预定的地址空间区域,调拨物理存储器后所有映射了同一个文件映射对象的的视图的其他进程就可以成功的访问已调拨的页面。

PS:稀疏调拨的内存映射文件尚未实例验证过,诸君谨慎参考。

【WIN32进阶之路】:内存映射文件的更多相关文章

  1. 内存映射文件详解-----C++实现

    先不说内存映射文件是什么.贴个代码先,. #include <iostream> #include <fcntl.h> #include <io.h> #inclu ...

  2. MemoryMappedFile 内存映射文件 msdn

    http://msdn.microsoft.com/zh-cn/library/dd997372%28v=vs.110%29.aspx 内存映射文件 .NET Framework 4.5 其他版本 1 ...

  3. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转

    原文:C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing ...

  4. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped

    节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). 内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作 ...

  5. .NET 4.0中使用内存映射文件实现进程通讯

    操作系统很早就开始使用内存映射文件(Memory Mapped File)来作为进程间的共享存储区,这是一种非常高效的进程通讯手段.Win32 API中也包含有创建内存映射文件的函数,然而,这些函数都 ...

  6. C++中使用内存映射文件处理大文件

    引言 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile().WriteFile().ReadFile() ...

  7. JAVA NIO之浅谈内存映射文件原理与DirectMemory

    JAVA类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...

  8. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 VC中进程与进程之间共享内存 .net环境下跨进程、高频率读写数据 使用C#开发Android应用之WebApp 分布式事务之消息补偿解决方案

    C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). ...

  9. 【VS开发】内存映射文件3

    内存映射文件 内存映射文件,是由一个文件到一块内存的映射.Win32提供了允许应用程序把文件映射到一个进程的函数 (CreateFileMapping).内存映射文件与虚拟内存有些类似,通过内存映射文 ...

随机推荐

  1. RedMine项目管理系统邮件推送设置(Windows环境)

    RedMine项目管理系统有邮箱推送功能,当Bug,安全漏洞等内容被修改.解决.评论的时候,系统会通过邮件 及时的通知你的团队和客户.邮件通知的环节.形式.时间.接受人均可定制,功能十分实用. 下面是 ...

  2. 利用循环removeChild删除节点只删除一半问题

    <!DOCTYPE html> <html>   <head>     <title>adduser.html</title>        ...

  3. 2014年最火的 21个JavaScript 框架

    下面,我们将会介绍 2014 年最火的 21 款JavaScript 框架,专为前端开发者准备的哦:)众所周知, JavaScript 框架是 JavaScript编程语言最棒的特性之一. JavaS ...

  4. 浩顺AC671指纹考勤机二次开发(demo)

    关于考勤机 AC671,是新换的机器,以前的那部机器,通过网络死活连接不上,换了AC671网络连接是好用了.但是,我要吐槽 浩顺的考勤机应该是卖了很多了吧,可是自带的软件太不给力,最后分析出来的数据一 ...

  5. linux应用程序问题

    ---- 1 ----

  6. Eclipse优化

    未特别说明,以下均处理在Window->Preferences下 General列表下 Startup and Shutdown可以去掉一些不必要的启动项 怎样才能知道哪些启动项有用呢?我现在把 ...

  7. WVGA-维基百科

    WVGA是一种屏幕分辨率的规格,其中的W意味宽(wide),长宽比为800×480.与之相关的还有VGA(640×480)和FWVGA(854×480). WVGA并不是16:9比例,而是5:3的显示 ...

  8. CSS sprites 技术

    Css Sprites 技术逐渐流行,各大网站上都可以看到它的身影. 但从本质上,Css Sprites 只是 Css 技术的一个使用小窍门,初学者也能快速上手. Css Sprites 简单解释: ...

  9. (转)MySQL数据库引擎ISAM MyISAM HEAP InnoDB的区别

    转自:http://blog.csdn.net/nightelve/article/details/16895917 MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎 ...

  10. 安装ejabberd2并配置MySQL为其数据库

    以前用过openfire做为服务器,但是openfire的集群支持不是很好,所以改用Ejabberd,由于它是用Erlang语言开发的,其并发率与分布式的功能都是很强悍的,在此我记录一下我的安装与配置 ...