《Windows核心编程系列》谈谈内存映射文件

发表于:2012-10-22 10:37

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:ithzhang    来源:51Testing软件测试网采编

  内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件。将文件映射到内存中后,我们就可以在内存中操作他们了,就像他们被载入内存中一样。

  内存映射文件主要有三方面的用途:

  1:系统使用内存映射文件来将exe或是dll文件本身作为后备存储器,而非系统页交换文件,这大大节省了系统页交换空间,由于不需要将exe或是dll文件加载到页系统交换文件,也提高了启动速度。

  2:使用内存映射文件来将磁盘上的文件映射到进程的空间区域,使得开发人员操作文件就像操作内存数据一样,将对文件的操作交由操作系统来管理,简化了开发人员的工作

  3:windows提供了多种进程间通信的方法,但他们都是基于内存映射文件来实现的。

  这里首先讨论第一种情况:

  在一个exe文件运行之前,系统首先为新进程创建一个进程内核对象,同时预订一块足够大的地址空间来容纳该文件。然后,对该地址空间进行标注,注明他的后备存储器来自exe文件,而非系统的页交换文件。此措施对提高系统性能有重大意义。

  一个可执行文件,当他有多个实例同时运行,系统在创建另一个新的实例时,仅仅是打开了另一个内存映射视图。所有这些视图都来自于同一个文件映射对象(即可执行文件本身)。

  当新实例开始运行时,系统只是把包含应用程序代码和数据的虚拟内存页面映射到了他的地址空间中,当其中的一个实例试图去修改数据段中的数据,如果不采取有效措施,那么应用程序的所有其他实例的内存都会被修改,这是不合常理的。因此windows采取了一种叫做写时复制的特性,来防止这种情况的发生。

  系统将可执行文件映射到地址空间中时,会计算有多少页面是可写的。(通常包含数据的页面被标记为PAGE_READWRITE属性,它们是可写的)然后会从系统的页交换文件中调拨物理存储器,来容纳这些可写的页面。但是系统只是调拨这些页面,并不会实际载入页面的内容,只有当写入可写页面的时候才会真正实际载入。(后面会详细介绍)

  任何时候当应用程序试图写入内存映射文件的时候,系统会截获此类尝试,接着从先前在系统页交换文件中分配的空间中取出一页,复制要写入页面的内容,让应用程序写入刚刚从系统页交换文件中分配的页,而不是内存映射文件中的页。由于写入到的区域仅仅是内存映射文件的副本,不会对内存映射文件写入,这样就保证了其他实例不会受到任何影响。另外需要注意的是,内存映射文件的副本(在系统页交换文件中)被映射到了新实例的地址空间区域的同一位置。

  以上介绍的是在同一个可执行文件的多个实例之间不会共享数据的情况。有时候在多个实例之间共享数据非常有用,可以大大提高编程效率。接着我们就讨论如何在一个可执行文件的多个实例中共享数据。

  我们知道默认情况下,我们定义的初始化数据被放到了数据段,未初始化的数据放到了.bss段。除了使用这些标准段之外,我们也可以将数据放在我们自己的段中。

  首先,就要知道如何创建一个段。

#pragm data_seg("sectionname")//创建一个名为sectionname的段。

  看例子:

#pragm data_seg("newsection")//此处创建一个名为newsection的段
int a=23;//向此段中添加变量。
#pragm data_seg()//结束添加

  此例创建了一个名为newsection的段,并向此段添加int类型变量a。#pragm data_seg()用于结束向段中添加数据。

  要注意一点编译器只会将以初始化的变量放入我们的段中,如上例中的a。

  如果这样:

#pragm data_seg("newsection")
int a=23;
int b;
#pragm data_seg()

  b是不会被添加到段newsection中的。而是放到默认的标准段中。

  虽然编译器只会将初始化的变量放入自定义段中,但是我们可以强制的将一个未初始化的数据放我任何我们想放入的段中。

  _declspec(allocate("newsection") ) int b;将b放入newsection中。

41/41234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号