现在的位置: 首页 > 综合 > 正文

Windows核心编程学习笔记–第15章

2013年10月03日 ⁄ 综合 ⁄ 共 1931字 ⁄ 字号 评论关闭

15章在应用程序中使用虚拟内存

        
Windows
提供了三种机制来对内存进行操控。

Ø  虚拟内存:最适合用来管理大型对象数组或大型结构数组。----本章讨论

Ø  内存映射文件:最合适用来管理大型数据流(通常是文件),以及在同一机器上运行的多个进程之间共享数据。----16

Ø  堆:最适合用来管理大量的小型对象。----17

再强调一次:虚拟内存最适合用来管理大型数组,无论是对象数据还是结构数组。

15.1预定地址空间区域

PVOID   VirtualAlloc(

PVOID  pvAddress,//NULL即可。

SIZE_T  dwSize,//想要预定区域的大小,字节为单位。因系统始终根据CPU页面大小的整数倍来预定区域,因此若在页面大小为4KB的机器上预定62KB大小的区域的话,最终得到的区域大小为64KB(4的整数倍)

DWORD  fdwAllocationType,//指明是预定区域还是调拨物理存储器。MEM_RESERVE用来预定地址空间区域。

DWORD  fdwProtect);//给区域指定保护属性,一般为PAGE_READWRITE。区域的保护属性和物理存储器的保护属性无关。未给区域调拨物理存储器时,试图访问区域内的任何内存地址都会引发访问违规。

返回值:成功返回预定区域的基地址,失败NULL

15.2给区域调拨物理存储器

         预定区域后,需给区域调拨物理存储器,这样才可访问其中的内存地址。调拨物理存储器时,起始地址始终都是页面大小的整数倍,整个大小也是页面大小的整数倍。

         通过VirtualAlloc,第三个参数用MEM_COMMIT。对在已预订的区域中,必须告诉VirtualAlloc要调拨多少物理存储器给哪里。通过pvAddress(想调拨物理存储器给哪个内存地址)dwSize(物理存储器的数量,以字节为单位。8位(bit=1字节(Byte,1024字节=1KB)来指定。此种方式用于对大型数组的操作。对不是在已预订区域中调拨,即直接调拨时,不必指明内存地址。当然更不必先预订虚拟内存了。

15.3同时预定和调拨物理存储器

         需给第三个参数传入MEM_RESERVE | MEM_COMMIT

15.4何时调拨物理存储器

         对一个电子表格,若它支持200行、256列。对每个单元格,我们需要一个CELLDATA结构来描述单元格的内容。对二维数组单元格最简单的操作方法,莫过于声明如下变量:CELLDATA 
CellData[200][256];
CELLDATA  结构大小为128字节,则此二维数组需要200*256*128字节的物理存储器。而对一个电子表格,大多数用户只会用到少数几个单元格,有没有觉得很浪费?

         若用链表方式,当电子表格的某个单元格中确实存放了数据时,才需创建与之对应的CELLDATA结构。节省大量物理存储器,但增大了读取单元格内容的难度,每次都得遍历。

         虚拟内存技术提供了一种折中方案:

1) 
预定一块足够大区域来容纳CELLDATA结构的整个数组。只预定区域不会消耗物理存储器。

2) 
当用户在某个单元格中输入数据时,首先确定CELLDATA结构在区域中的内存地址。因还未给地址映射物理存储器,因此访问该内存地址将引发访问违规。

3) 
给第2步中的内存地址调拨物理存储器。

4) 
设置CELLDATA结构的成员。

存在的问题:必须确定什么时候需要调拨物理存储器。若只是编辑或修改单元格中数据,就不必再调拨物理存储器。有两种方式可确定是否需要给区域中某一部分调拨物理存储器:

1) 
总是调拨物理存储器。若已调拨,系统将不再调拨,返回NULL

2) 
使用结构化异常处理(SEH)------最佳方案。23-25章讲。

15.5撤销调拨物理存储器及释放区域

BOOL  VirtaulFree(

         LPVOID  pvAddress,

         SIZE_T  dwSize,

         DWORD fdwFreeType);

         dwSize0pvAddress又是区域的基地址(即预订区域时VirtualAlloc返回的地址),则VirtaulFree会释放整个区域及调拨给该区域的物理存储器。第三个参数为MEM_RELEASE,告诉系统释放为该区域预订的所有地址空间。

         若想撤销调拨给区域的一部分物理存储器,但又不想释放整个区域,则需指定内存地址给pvAddress,用来告诉系统想撤销调拨的第一个页面的地址;dwSize中指定想要释放的物理存储器的大小;并传MEM_DECOMMIT给第三个参数。

抱歉!评论已关闭.