一、内存映射

内存映射文件允许开发人员预定一块地址空间区域并给区域调拨物理存储器。内存映射文件的物理存储器来自磁盘已有的文件,而不是来自系统的页交换文件。一旦把文件映射到地址空间,就可以对它进行访问,就好像整个文件都已经被载入内存一样。不必再对文件执行I/O操作。

使用内存映射文件来颠倒文件内容时,先打开文件并向系统预订一块虚拟地址空间区域。接着让系统把文件的第一个字节映射到该区域的第一个字节,然后就可以访问这块虚拟内存区域,就好像它实际上包含了文件一样。优点:在于系统为我们处理所有与文件缓存有关的操作,不必再分配任何内存,把文件中的数据载入内存,把数据写回文件,以及释放内存。

内存映射文件有三种,第一种是可执行文件的映射,第二种是数据文件的映射,第三种是借助页面交换文件的内存映射.应用程序本身可以使用后两种内存映射.

过程

1.创建或打开一个文件内核对象。该对象标识了我们想要用作内存映射文件的那个磁盘文件。CreateFile().

2.创建一个文件映射内核对象来告诉系统文件的大小以及如何访问文件。CreateFileMapping()

3.告诉系统把文件映射对象的部分或者全部数据映射到进程的地址空间。MapViewOfFile();

4.从进程的地址空间撤销对文件数据的映射。UnmapViewOfFile();

5.关闭文件映射对象和文件对象。

数据的一致性

把同一文件中的数据映射到多个视图中,如果应用程序在一个视图中作了修改,那么系统会更新所有其他视图以反映修改后的内容。因为,该页面被多次映射到进程的虚拟地址空间,系统在同一个内存页面中保存被映射的数据。

若果多个进程把同一数据文件映射到多个视图,数据依然保持一致性。因为数据文件中的每个页面在内存中只有一份,但这些内存页面会被映射到多个进程的地址空间中。

若一个应用程序想要调用createfile来打开文件,但另外一个进程已经映射了同一个文件。为了防止一读一些ReadFile和WriteFile,可以设置为独占模式。

由于只读文件不存在一致性问题,非常适合内存映射文件,决不允许内存映射文件来跨网络共享可写文件,因为系统无法保证数据视图的一致性。如果一台机器更新了内容,另外一台机器无法知道。

1.可执行文件映射:
  Windows在执行一个Win32应用程序时使用的是内存映射文件技术.系统先在进程地址空间的0x00400000以上保留一个足够大的虚拟地址空间(0x00400000以下是由系统管理的),然后把应用程序所在的磁盘空间作为虚拟内存提交到这个保留的地址空间中去(我的理解也就是说,虚拟内存是由物理内存和磁盘上的页面文件组成的,现在应用程序所在的磁盘空间就成了虚拟地址的页面文件).做好这些准备后,系统开始执行这个应用程序,由于这个应用程序的代码不在内存中(在页面文件中),所以在执行第一条指令的时候会产生一个页面错误(页面错误也就是说,系统所访问的数据不在内存中),系统分配一块内存把它映射到0x00400000处,把实际的代码或数据读入其中(系统分配一块内存区域,把它要访问的在页面文件中的数据读入到这块内存中,需在注意是系统读入代码或数据是一页一页读入的),然后可以继续执行了.当以后要访问的数据不在内存中时,就可以通过前面的机制访问数据.对于Win32DLL的映射也是同样,不过DLL文件应该是被Win32进程共享的(我想应该被映射到x80000000以后,因为0x80000000-0xBFFFFFFF是被共享的空间).

  当系统在另一个进程中执行这个应用程序时,系统知道这个程序已经有了一个实例,程序的代码和数据已被读到内存中,所以系统只需把这块内存在映射到新进程的地址空间即可,这样不就实现了在多个进程间共享数据了吗!然而这种共享数据只是针对只读数据,如果进程改写了其中的代码和数据,操作系统就会把修改的数据所在的页面复制一份到改写的进程中(我的理解也就是说共享的数据没有改变,进程改写的数据只是共享数据的一份拷贝,其它进程在需要共享数据时还是共享没有改写的数据),这样就可以避免多个进程之间的相互干扰.

2.数据文件的内存映射:
  数据文件的内存映射原理与可执行文件内存映射原理一样.先把数据文件的一部分映射到虚拟地址空间的0x80000000 - 0xBFFFFFFF,但没有提交实际内存(也就是说作为页面文件),当有指令要存取这段内存时同样会产生页面错误异常.操作系统捕获到这个异常后,分配一页内存,映射内存到发生异常的位置,然后把要访问的数据读入到这块内存,继续执行刚才产生异常的指令(这里我理解的意思是把刚才产生异常的指令在执行一次,这次由于数据已经映射到内存中,指令就可以顺利执行过去),由上面的分析可知,应用程序访问虚拟地址空间时由操作系统管理数据在读入等内容,应用程序本身不需要调用文件的I/O函数(这点我觉得很重要,也就是为什么使用内存映射文件技术对内存的访问就象是对磁盘上的文件访问一样).

3.基于页面交换文件的内存映射:
  内存映射的第三种情况是基于页面交换文件的.一个Win32进程利用内存映射文件可以在进程共享的地址空间保留一块区域(0x8000000 - 0xBFFFFFFF),这块区域与系统的页面交换文件相联系.我们可以用这块区域来存储临时数据,但更常见的做法是利用这块区域与其他进程通信(因为0x80000000以上是系统空间,进程切换只是私有地址空间,系统空间是所有进程共同使用的),这样多进程间就可以实现通信了.事实上Win32多进程间通信都是使用的内存映射文件技术,如PostMessage(),SentMessage()函数,在内部都使用内存映射文件技术.

数据共享

在Windows中,在同一台机器上数据共享的最底层机制就是内存映射文件。
这种数据共享机制是通过让两个或多个进程映射同一个文件映射对象的视图来实现,意味着在进程间共享相同的物理存储页面。对多个进程共享同一个文件映射对象来说,所有进程使用的文件映射对象的名称必须完全相同。 《windows核心编程》 p473

虚拟内存

共享内存

<1>共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。

<2>为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一块内存而不需要进行数据的拷贝,从而大大提高效率。

<3>由于多个进程共享一段内存,因此也需要依靠某种同步机制。

实现

共享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,这样每个进程都可以读取同一份数据,从而实现进程通信。因为是通过内存操作实现通信,因此是一种最高效的数据交换方法。
1、调用 CreateFileMapping 创建一个文件映射内核对象;

通过这个API函数 将创建一个内存文件映射的内核对象,用于文件映射到内存。与虚拟内存一样,内存文件映射可以用来保留一个地址空间的区域,并将物理存储器提交给该区域。它们之间的差别是,物理存储器来自一个已经位于磁盘上的文件,而不是系统的页文件。

2、调用 MapViewOfFile 映射到当前进程的虚拟地址上;

将内存映射文件映射到进程的虚拟地址中

3、在接收进程中打开对应的内存映射对象

在数据接收进程中,首先调用OpenFileMapping()函数打开一个命名的文件映射内核对象,得到相应的文件映射内核对象句柄hFileMapping;如果打开成功,则调用MapViewOfFile()函数映射对象的一个视图,将文件映射内核对象hFileMapping映射到当前应用程序的进程地址,进行读取操作。(当然,这里如果用CreateFileMapping也是可以获取对应的句柄)

4.调用完之后,清理
//取消本进程地址空间的映射;
UnmapViewOfFile(pLocalMem);
//关闭文件映射内核文件
CloseHandle(hFileMapping);

数据共享,内存映射文件和虚拟内存,共享内存相关推荐

  1. c++ 内存映射文件进程间共享数据

    int main(int argc, char *argv[])   {       //RecursiveDelete("C:\\20_128\\");       //Self ...

  2. mmap内存映射、system V共享内存和Posix共享内存

    linux内核支持多种共享内存方式,如mmap内存映射,Posix共享内存,以system V共享内存.当内核空间和用户空间存在大量数据交互时,共享内存映射就成了这种情况下的不二选择.它能够最大限度的 ...

  3. linux共享内存示例,linux 进程间共享内存示例

    写入端: #include #include #include #include #include using namespace std; struct MappingDataType { int ...

  4. C#内存映射文件学习总结

    C#内存映射文件学习 http://www.cnblogs.com/flyant/p/4443187.html 内存映射文件是由一个文件到进程地址空间的映射. C#提供了允许应用程序把文件映射到一个进 ...

  5. VC++中使用内存映射文件处理大文件

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

  6. Windows核心编程 第十七章 -内存映射文件(下)

    17.3 使用内存映射文件 若要使用内存映射文件,必须执行下列操作步骤: 1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件. 2) 创建一个文件映射内核对象,告诉系统该 ...

  7. 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件

    本文背景: 在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用:根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制. 本 ...

  8. windows 内存映射文件

    4.内存管理机制--内存映射文件 (Map)    和虚拟内存一样,内存映射文件可以用来保留一个进程地址区域:但是,与虚拟内存不同,它提交的不是物理内存或是虚拟页文件,而是硬盘上的文件. ·使用场合 ...

  9. 内存映射文件使用详细

    http://www.cppblog.com/woaidongmao/archive/2008/12/26/70439.html 摘要: 本文通过内存映射文件的使用来对大尺寸文件进行访问操作,同时也对 ...

最新文章

  1. c malloc 头文件_C 数据类型
  2. redhat 安装Rabbitmq
  3. 天池 在线编程 所有子数组之和(排列组合)
  4. 【MySQL通过视图(或临时表)实现动态SQL(游标】
  5. 斯坦纳树算法概述及习题
  6. python分析视频文件_FLV视频文件格式分析
  7. 天正的计算机快捷命令大全,天正建筑命令快捷键大全
  8. goeasy java_Java GoEasy 实现服务端推送和Web端推送
  9. 解决“ssh服务器拒绝了密码 请再试一次”问题
  10. 小米开源便签Notes-源码研究(0)-整体功能介绍(图文并茂)
  11. 【Scratch算法讲解】01-Scratch选择排序 少儿编程Scratch常见排序算法案例分析讲解
  12. UDS(一)入门概述
  13. VVIC搜款网平台API接口
  14. 请冷静地对待手中的EOS——EOS数据分析
  15. 【css】图片的内容阴影处理
  16. Java实现png图片转pdf
  17. linux中fstab文件_如何在Linux上写入fstab文件
  18. shell md5sum命令
  19. mmd动作:FREELY_TOMORROW
  20. 蜜罐蜜网_Hack hell(概述)

热门文章

  1. 常见算法讲解及实例——二分搜索法
  2. PADS灌注(flood)和填充(hatch)(总结)
  3. CIO:知道谁会购买iPhone 7吗?
  4. DJ7-4 模型机的组合逻辑控制器
  5. 651页23万字智慧教育大数据信息化顶层设计及智慧应用建设方案
  6. html列表的伸缩跟舒展,舒展的意思是什么
  7. SAP Number range 编号范围用法
  8. 我的世界java怎么设置高性能,我的世界java优化指南_我的世界如何流畅运行_玩游戏网...
  9. 中国政府针对财务体系赋能企业科技创新颁布了哪些政策
  10. win10 KB5018410累积更新后开关机出现黑屏