在Win32中管理虚拟内存

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

在Win32中管理虚拟内存 开发技巧-系统应用 2005-07-14 首页 收藏本站 帮助信息 广告服务 购买方法 联系我们



首页 |源码下载中心 |技术论坛 |控件 |书籍教程 |源码商城 |博客 |商业源码 |开发技巧 |系统设计方案 |手机短信送歌 |免费PHP空间






会 员 登 录



用户名:
密 码:
新会员注册 忘记密码




升级白金会员
会员中心
发布源码
发布控件
发布开发工具
短信中心
我的相册
设置我的讨论组
我的好友
修改资料




相 关 工 具 下 载

FTP工具 AbsoluteFTP 2.04


合 作 伙 伴



个 人 专 栏

tomore







您所在的位置: 首页 -> 开发技巧 -> 系统应用 ->详细内容

·网络应用(233)·数据库应用(187)·多媒体(48)·界面设计(94)
·打印技巧(36)·图象应用(57)·系统应用(332)·其他技巧(423)



资源名称在Win32中管理虚拟内存
作者:未知
适用语言:
文件大小18897
运行平台:
上传者:
上传日期:2005-06-06 18:04:25
点击:12
简介在Win32中管理虚拟内存

Randy Kath

Microsoft Developer Network 技术小组

创建于:1993年1月20日

单击此处以打开或复制 ProcessWalker 示例程序中的文件。该Win32
示例程序要求Microsoft Windows NT 的环境。

摘要

在Microsoft Windows NT 操作系统中,假如您对每组函数的功能,
以及它们每个函数的作用,没有足够的认识,那么在Win32 应用程序中,
决定使用哪个函数,或者哪组函数来管理内存将是困难的。为了简化这个
问题,本篇技术文章主要是围绕Win32虚拟内存管理函数的:它包括哪些
函数是可用的、如何使用它们,以及使用它们会对操作系统产生什么影响。
本文将讨论如下的主题:

保留、提交,和释放虚拟内存
在虚拟内存页上改变

保护
锁定虚拟内存页
查询一个进程的虚拟内存
在Microsoft Developer Network CD中有一个叫作ProcessWalker的示例程序,
它将会在本篇技术文章中出现。该示例程序对于探索一个进程的内存地址空
间是很有用的。它还使用了虚拟内存函数来实现一个相互链接的列表结构。

 

概述

本文是三篇相关技术文章中的其中一篇,这三篇文章分别是棗“在Win32中管理虚拟内存
”、“在Win32中管理内存-映射文件”,以及快要完成的“在Win32中管理堆(heap)内
存”棗它们解释了如何在Win32编程接口的应用程序中管理内存。在每篇文章的概述部分
,要指明Win32编程模型中基本的内存部件,并且指出如果您对特殊领域的较有兴趣,那
么应该参考哪一篇文章。

Microsoft Windows 操作系统的第一个版本介绍了基于一个单个的全局堆(global heap
)和多个专有的局部堆(local heaps)来管理动态内存的方法,所有应用程序和系统共
存该全局堆(global heap),而每一个应用程序具有其单独的局部堆(local heaps)
。同时还提供了全局和局部的内存管理函数,为这种新的内存管理系统提供了扩展的特
性。最近,Microsoft C的运行时(CRT)库被修改以包含如下功能,即使用如malloc和
free这样的纯粹的CRT函数来管理Windows中的堆。所以,现在开发者应该作出选择了棗
要么学习作为Windows 3.1版本的一部分来提供的新的应用程序编程接口(API),要么坚
持使用可移植的、典型的、并且为人所熟悉的CRT函数在为Windows 3.1所编写的应用程
序中管理内存。


随着Win32 API内容的不断增加,选择机会也随之增加。Win32提供了三个附加的函数组
来管理应用程序的内存:内存-映射(memory-mapped)文件函数、堆内存(heap memory
)函数,以及虚拟内存函数。这些新的函数并不替代在Windows 3.1中现存的内存管理函
数;相反它们提供了新的特性,使得开发者在为他们的Win32应用程序编写内存管理部分
时,日子会轻松得多。


图1. Win32 API为应用程序编程的多样性提供了不同级别的内存管理。

总之,如图1所看到的,在Win32中有六组内存管理函数,所有这些函数都被设计成单独
使用。所以,您应该使用哪种

函数呢?要回答这一问题主要依靠以下两件事:您希望的
内存管理类型是什么,以及与之相关联的函数在操作系统中是如何实现的。换句话说,
您是否是正在建立一个大的数据库应用程序,因而希望操作一个大的内存结构的子集合
,或者您正计划一些简单的动态内存结构,例如链接列表或二进制树(binary trees)
。在这两种情况下,您都需要搞清楚哪些函数提供的功能最适合您的意向,并确切地了
解在使用每个函数时要占用多少资源。


表1将Win32中的内存管理函数组进行了分类,并且分别指出在本系列的三篇技术文章中
,每一篇所描述的相关的组的行为。在每篇技术文章中,通过描述作为对使用这些函数
的响应的系统行为,重点强调了这些函数对系统所产生的影响。

表1. 在Win32中可用的内存管理函数

内存设置 受影响的系统资源 相关的技术文章
虚拟内存函数 一个进程的虚拟地址空间
系统页文件

系统内存

硬盘空间
“在Win32中管理虚拟内存”
内存-映射文件函数 一个进程的虚拟地址空间
系统页文件

标准文件I/O

系统内存

硬盘空间
“在Win32中管理内存-映射文件”
堆(Heap)内存函数 一个进程的虚拟地址空间
系统内存

进程堆资源结构
“在Win32中管理堆内存”
全局堆内存函数 一个进程的堆资源结构 “在Win32中管理堆内存”
局部堆内存函数 一个进程的堆资源结构 “在Win32中管理堆内存”
C运行时参考库 一个进程的堆资源结构 “在Win32中管理堆内存”

每篇技术文章都是围绕Win32函数的用途问题而展开讨论的。要想对Windows NT操作系统
如何管理系统内存有更详细的了解,请参阅Microsoft Developer Network CD上的“The
Virtual-Memory Manager in Windows NT”(技术文章,Win32和Windows
NT的文章)。

 

Windows NT内存系统概述

Windows NT使用一个以页为基础的虚拟内存系统,该系统使用32位线性地址。在内部,
系统管理被称为页的4096字节段中的所有内存。每页的物理内存都被备份 ?/FONT> 对于
临时的内存页使用页文

件(pagefile),而对于只读的内存页,则使用磁盘文件。在同一
时刻,最多可以有16个不同的页文件。代码、资源和其它只读数据都是通过它们创建的
文件直接备份。

Windows NT为系统中的每一个应用程序(进程)提供一个独立的、2 GB的用户地址空间
。对于应用程序来说,好象是有2 GB的可用内存,而不用考虑实际可用的物理内存的量
。如果某个应用程序要求的内存比可用的内存更多时,Windows NT是这样满足这种要求
的,它从这个和/或其他的进程把非关键内存分页(paging)到一个页文件,并且释放这些
物理内存页。结果,在Windows NT中,全局堆不再存在。相反,每一个进程都有其自己
的32位地址空间,在其中,该进程的所有内存被分配, 包括代码、资源、数据、DLL(动
态链接库),和动态内存。实际上,系统仍然要受到可用的硬件资源的限制,但是实现
了与系统中应用程序无关的、对于可用资源的管理。

 

在Win32中的虚拟内存

Windows NT在内存和地址空间之间作出了区分。每个进程分配到2 GB的用户地址空间,
而不管对于该进程的实际可用物理内存有多少。而且,所有进程都使用相同范围的线性
32位地址,范围从0000000016-7FFFFFFF16,而不考虑可用内存的地址。Windows NT负责
在适当的时间把内存页映射(paging)到磁盘以及从磁盘页映射回内存,使得每个进程都
确保能够寻址到它所需要的内存。尽管有可能出现两个进程试图同时访问同一虚拟地址
上的内存,但是,实际上Windows NT虚拟内存管理程序是在不同的物理位置描述这两个
内存的位置。而且这两个地址都不见得与原始的虚拟地址一致。这就是虚拟内存。

因为虚拟内存的存在,一个应用程序能够管理它自己的地址空间,而不必考虑在系统中
对于其它进程的影响。在Windows NT中的内存管理程序负责查看在任何给定的时间里,
所有的应用程序是否有足够的物理内存进行有效的操作。与在Windows 3.1版本或更早的
版本中不同,Windows NT操作系统下的应用程序不必考虑和其它应用程序共享系统内存
这个问题。并且,即使在应用程序自己的地址空间内,它们仍能够与其它的应用程序共
享内存。

区分内存和地址空间的一个好处是,为应

用程序提供了将非常大的文件加载到内存的能
力。不必将一个大的文件读进内存中,Windows NT为应用程序保留该文件所需的地址范
围提供了支持。然后,在需要的时候,该文件部分就可以被浏览了(物理性地读进内存
)。通过虚拟内存的支持,对于大段的动态内存的分配同样可以做到这一点。

在Windows的早期版本中,在一个应用程序能够操作内存中的地址之前,该应用程序必须
首先分配内存。在Windows NT中,每一个进程的地址空间已经分配好了,是否有内存与
该段地址空间中的地址相关联是另外的问题。Win32虚拟内存管理函数为分别管理进程的
地址和内存提供了低级别的支持。

Win32虚拟内存函数的全体是:

VirtualAlloc 和 VirtualFree
VirtualLock 和 VirtualUnlock
VirtualQuery 或 VirtualQueryEx
VirtualProtect 或 VirtualProtectEx
对于每个函数,如有与之相对应的,则它们共同组成一组。分配内存请使用
VirtualAlloc,一旦已经分配,则必须使用VirtualFree来释放。类似地,对于被使用
VirtualLock锁定的页,当不再需要时,则必须用VirtualUnlock来解除锁定。
VirtualQuery和VirtualProtect没有与之相对应的函数,但它们俩都有完整功能
(complementary)的函数(在函数名字上的Ex扩展来指示)。这样,就允许它们在除调用
进程之外的其他进程中使用,但是,此时调用进程需要有适当的特权才可以这样。这些
函数将在下面的适当的上下文中解释。

 

自由的、保留的和已提交的虚拟内存

在任意给定的时间,进程中每个地址都可以被当作是自由的、保留的或已提交的。进程
开始时,所有地址的都是自由的,意味着它们都是自由空间并且可以被提交到内存,或
者为将来使用而保留起来。在任何自由的地址能够被使用前,它必须首先被分配为保留
的或已提交的。试图访问一个保留的或已提交的地址都将产生一个访问冲突异常(access
violation exception)。

一个进程中的所有2 GB的地址要么为了使用而是自由的、要么为了将来的使用而是保留
的、要么已提交到特定的内存(在使用的)。图2描述了一个假设的进程,它包含自由的
、保留的和已提交的地址。

图 2.

一个进程的2 GB的虚存地址空间被分配为自由的、保留的和已提交的内存区位置。

 

保留的地址

当在一个进程中保留地址时,没有物理内存页被提交,并且,也许更为重要的是,在页
文件中没有为备份该内存而保留空间。而且,保留一个地址范围将不会保证将来会有可
用的物理内存来提交给这些地址。实际上,它只是保存了一个指定的自由地址地址,一
直到需要使用它时,而阻止了其它分配对该段地址的请求。如果没有这种类型的保护,
那么例程操作(routine operations),例如加载一个DLL或者资源,可能会占有指定的地
址,并且危害以后对它的使用。


保留地址是一个快速的操作,完全与被保留的地址范围的大小没有关系。不论保留1 GB
的地址范围,还是保留4K的地址范围,该函数的速度都非常快。这并不令人惊奇,因为
在此操作期间,没有资源被分配。该函数只是进入进程的虚拟地址描述符(VAD)树。有关
VAD的详细信息,请参阅 Developer Network CD 的“The Virtual-Memory Manager
in
Windows NT”(技术文章,Win32和Windows NT文章)

要想保留一段地址范围,需要参照下列代码来调用VirtualAlloc函数:

/* 保留 10 MB 的地址空间 */

lpBase = VirtualAlloc (NULL,

10485760,

MEM_RESERVE,

PAGE_NOACCESS);

如这里所示,第一个参数,lpAddress,使用的是NULL值,指导该函数在某一个最方便的
位置保留地址范围。另外,也可能一个指定的地址已经被传递,为要保留的范围指示一
个准确的初始地址。无论两种方法中的哪一种,该函数的返回值都指示出被保留的地址
范围的开始位置,除非该函数无法完成请求。要是这样,VirtualAlloc函数的返回值将
是一个错误状态值。


第二个参数指示函数应该分配的地址范围。该值的大小可以是从一页到2 GB的任意值,
但是VirtualAlloc实际上被限制为一个较小的范围。能够被保留的最小值为64K,而能够
被保留的最大值为该进程中最大的连续自由地址空间。请求的保留地址,结果是得到64K
的地址范围。反之,请求2 GB的范围将会失败,因为在任何给定的时间里,有那么多的
可用地址空间是不可能的。(请记住,加载

一个应用程序的动作也要使用初始2 GB地址
空间中的一部分。)

注意 Windows NT在每一个进程的地址空间中生成一个保护设施(safeguard)。每一个进
程的顶端65,536字节和低端65,536字节都被系统永久地保留。这些地址空间部分被保留
为陷阱迷失指针(trap stray pointers)棗试图在0000000016-0000FFFF16或
7FFF000016-7FFFFFFF16范围内寻址内存的指针。并不是巧合,在这个范围内,只需忽略
这些地址中的低四位(最右边的两个字节)就可很容易地检测到该指针。从根本来讲,
如果高四位是000016或7FFF16,那么这个指针是无效的;所有其它的值都表示有效的地
址。

在VirtualAlloc函数中的最后两个参数,dwAllocationType和dwProtect被用来决定如何
分配地址以及与它们相关联的保护。地址可被分配为MEM_COMMIT或者MEM_RESERVE类型。
PAGE_READONLY、PAGE_READWRITE和PAGE_NOACCESS是三种可以被应用到虚拟内存的保护
。无论何值被传递到该函数,被保留的地址总是PAGE_NOACCESS,这是系统强制的默认值
。已提交的页可以是只读的、也可以可读写的,或者是不能访问的。

 

已提交的内存

要使用保留的地址,内存首先必须被提交给该地址。提交内存到地址与保留内存相类似
棗调用VirtualAlloc,并且在调用时设置dwAllocation参数等于MEM_COMMIT。在这一时
刻,资源被提交到地址上。每一次,内存可以按一页的大小被提交。能够被提交的最大
内存值仅仅取决于连续的自由或者保留地址的最大范围(但两者不可组合在一起),无
须考虑系统的可用物理内存的大小。

当内存被提交时,内存物理页被分配,并且该段空间被保留在在一个页文件中。也就是
说,已提交的内存页总是以物理内存页或者在已经被分页的磁盘上的页文件的形式存在
。当提交一个大块内存时,在初始阶段,其部分或者全部内存没有驻留在物理内存中也
是有可能的。某些内存页一开始驻留在页文件中,直到它被访问。在系统中,一旦内存
页已提交,虚拟内存管理器象对待所有其它的内存页一样对待它们。

在Windows NT虚拟内存系统中,使用了页表(page tables)来访问物理内存页。每个页
表本身也是一个内存页,象已提交的页一样。偶而,当提交内存

时,同时还必须对页表
分配附加的页。所以,提交一页内存的请求可能需要为页表分配一页,为请求的页分配
一页,并且在页文件中需要两页空间来备份这些页中的每一页。因此,VirtualAlloc完
成一个内存提交请求所需要的时间变化很大,它取决于系统的状态以及请求的空间大小


下面的示例演示了如何将上例中被保留地址的指定页提交到一个内存页中。

/* 为第3页地址提交内存。 */

lpPage3 = VirtualAlloc (lpBase + (2 * 4096),

4096,

MEM_COMMIT,

PAGE_READWRITE);

请注意,对于lpAddress没有指定为NULL,而是指定了一个特定的地址来准确地指示被保
留地址的哪一页会变成提交给内存的页。而且,初始时该内存页被赋予PAGE_READWRITE
保护,而不是象在前面示例中的PAGE_NOACCESS。该函数的返回地址是第一页已提交地址
的虚拟地址。

 

释放虚拟内存

一旦地址被以保留的或者已提交的形式分配,VirtualFree是唯一可以释放它们的方法棗
那就是,将它们返回到自由的地址。VirtualFree还可以用来对已提交的页解除提交,同
时,返回这些地址到保留状态。当解除地址的提交时,所有与该地址相关的物理内存和
页文件空间都被释放。下面的示例演示如何对在前一个示例中已提交的内存页解除提交


/* 对第3页地址解除提交内存。 */

VirtualFree (lpBase + (2 * 4096),

4096,

MEM_DECOMMIT,

PAGE_NOACCESS);

只有已提交的地址才能被解除提交。当您需要对一个大范围的地址解除提交时,牢记这
一点是非常重要的。例如,假设您有一定范围的地址,在其中多个地址的子集已被提交
,而其它部分被保留。要想使全部范围的地址保留,唯一方法就是一个一个地对每个被
提交的地址子集解除提交。如果试图对整个范围的地址解除提交将会失败,因为保留的
地址无法解除提交。


与之相反,在一次操作中相同范围的地址都能被释放。因为在地址被释放时,一个地址
的状态并不重要。下面的示例演示释放在第一个示例中被保留的10 MB范围的地址。

/* 释放整个 10 MB 范围的地址。 */

VirtualFr

ee (lpBase,

10485760,

MEM_RELEASE,

PAGE_NOACCESS);

 

改变虚拟内存页的保护

Win32提供VirtualProtect函数,作为对已提交内存改变页保护的一个方法。例如,一个
应用程序可以按PAGE_READWRITE来提交一个页的地址,并且立即将数据填写到该页中。
然后,该页的保护将被改变为PAGE_READONLY,这样可以有效地保护数据不被该进程中的
任何线程重写。下面的示例使用VirtualProtect函数使一个不能被访问的页可用。


/*将页保护改变成可读/写。*/

VirtualProtect (lpStack + 4096,

4096,

PAGE_READWRITE,

lpdwOldProt);

可以将下面的环境看作是使用该函数的环境。一个用于缓冲数据的应用程序接收到一组
大小变化的数据流,根据特定的硬件配置和其它的软件应用程序对CPU时间的竞争,数据
流可能某时(at times)超出进程的能力。为了防止这种现象发生,应用程序设计了一个
内存系统,可以在开始时为一个缓冲提交一些内存页。然后,应用程序则使用
PAGE_NOACCESS保护来保护内存的顶端页,使得任何想要访问该内存的请求都会产生一个
异常。应用程序也在该代码的外层代码中使用一个异常处理程序来处理访问冲突。

当一个访问冲突发生时,应用程序能够确定缓冲区是否已经到了其极限。该应用程序通
过将页保护改变为PAGE_READWRITE来响应,允许该缓冲区接收任何附加的数据,并且继
续不间断的执行。同时,应用程序加载另一个线程来减缓数据流,直到该缓冲区恢复到
一个理想的操作范围。当情况恢复到正常,顶端的页又返回到PAGE_NOACCESS,并且附加
的线程也结束了。这种情况描述了在Win32中,如何将页保护和异常处理程序结合使用来
提供独一无二的内存管理机会。

 

锁定虚拟内存页

在Windows NT中的进程有一个被称为工作组(working set)的最小页,是为了进程能够
顺利地运行,在运行时在内存中必须被提供。Windows NT在启动时为一个进程分配了默
认数量的页数,并且逐渐地调整该数,使得系统中所有激活的进程的性能达到一种平衡
的最优。当一个进程正在运行时(实际上是,是一个进程的线程正在运行时),Windows

NT在“努力工作”以确保该进程的工作组页总是驻留在物理内存中。

在Windows NT中的进程被授权使用VirtualLock和VirtualUnlock函数来巧妙地影响该系
统的行为。从根本上讲,一个进程可以建立特定的页将它锁定到工作组中。然而,这并
不给进程的工作组以自由的范围。它不能影响组成它的工作组的页数,(系统为每一个
进程按规范来调整工作组),并且它无法控制何时工作组在内存中以及何时不在内存中
。每次一个进程的工作组锁住的页数码最多不超过32。如果一个应用程序将被提交的内
存页锁定在工作组中,这样做可能利大于弊,因为这样做可能会迫使该进程中的其他关
键页被替代。如果那样的话,页可能会页映射到磁盘,在被访问的任何时候都会发生页
故障。于是,该进程将花费许多的CPU时间却只是将关键页映射到内存和映射出内存。



请牢记,在Win32中锁定一页内存并不意味着该页内存将不能被页映射到磁盘。相反,它
意味着当进程正在运行时,被锁定的内存页将是在一段物理内存中。不仅仅是有可能,
而是非常可能,当一个进程处于理想情况时,该进程的整个页的工作组将被页映射到磁
盘。当该进程的工作情况变差时,则工作组页将立即被页映射回内存中,包括
VirtualLocked 页。

下面的例子在进程运行时,锁定一段地址到内存中。

/* 锁定关键地址(critical addresses)到内存中。*/

VirtualLock (lpCriticalData, 1024);

请注意,在本例中被锁定到内存的地址范围小于一页。并不是必需要整段范围都在内存
的单个页中。最后的结果(net result)是包含该地址中的数据的整页的内存被锁定到内
存,而不仅仅是指出的地址的数据被锁定到内存中。如果该数据跨越了页的边界,则两
页都将被锁定。

 

查询一个进程的虚拟内存

给定一个进程的地址空间为2 GB,如果没有查询地址信息的能力,那么想要管理地址的
全部范围将是困难的。因为地址本身代表独立的内存,对于它们,这些内存有可能被提
交,或者不被提交,对它们进行查询,仅仅是读取保存它们状态的数据结构一件事罢了
。在Windows NT中,该结构是以前提到过的虚拟地址描述符树。Win32在VirtualQuery


VirtualQueryEx函数中提供了“遍历VAD结构”的能力。同样,Ex后缀指出哪个函数可从
一个进程中被调用来查询另一个进程棗假如调用进程有足够的安全特权来执行该函数。
下面的示例是从ProcessWalker示例程序中分离出来的:


/*查询子进程中的下一个内存区。*/

VirtualQueryEx (hChildProcess,

lpMem,

lpList,

sizeof (MEMORY_BASIC_INFORMATION));

ProcessWalker应用程序的主函数是遍历一个进程的地址空间,标识它的每一个唯一的地
址区,并且显示有关每个区的特定状态信息。它是通过每次枚举从进程底部到上部的每
个区域来完成的。LpMem被用来指出每个区域的位置。开始时它被设为0,从每个新区域
的查询返回后,它通过查询的区域大小而递增。该过程一直重复下去,直到lpMem达到系
统最高的保留区域。


LpList是一个指向MEMORY_BASIC_INFORMATION结构的指针,该结构被VirtualQueryEx函
数所填充。当该函数返回时,该结构代表被查询区域的有关信息。该结构包含下列成员


typedef struct _MEMORY_BASIC_INFORMATION { /* mbi */

PVOID BaseAddress; /* 区域的基本地址 */

PVOID AllocationBase; /* 分配基本地址 */

DWORD AllocationProtect; /* 初始访问保护 */

DWORD RegionSize; /* 区域的字节大小 */

DWORD State; /* 已提交的、保留的、自由的 */

DWORD Protect; /* 当前访问保护 */

DWORD Type; /* 页类型 */

} MEMORY_BASIC_INFORMATION;

VirtualQuery函数将为任何连接的地址区域返回这种状态信息。函数确定区域的底层边
界和区域的大小,以及该区域中的地址的确切状态。它用于确定该区域的地址可以是该
区域中的任何地址。因此,如果您想确定在任何给定的时间里有多少堆栈空间已经被提
交,请按照这些步骤进行:

为问题中的线程取得线程环境。
调用VirtualQuery函数,将线程环境信息中的堆栈指针地址作为函数中lpMem参数来提供。
该查询返回被提交内存的大小,并且分别以RegionSize和BaseAddres的形式返回在
MEMORY_BASIC_INFORMATION结构中基本堆栈的地址。

内存区域,由VirtualQueryRegions来定义,是一个连续的地址范围,其保护、类型和基

本分配是相同的。类型和保护值在本篇技术文章的前面曾做过描述。基本分配是
lpAddress参数值,当整个内存区域通过VirtualAlloc函数第一次被分配时该参数被使用
。在MEMORY_BASIC_INFORMATION结构中,它作为AllocationBase字段被表示出来。


当自由的地址成为保留的或已提交的情况时,那时它们的基本分配被确定。从任何角度
来说,内存区域都不是静态的。一旦在保留地址区域中的一个单页被提交,则该区域被
分成一个或多个保留区域和一个被提交区域。当页内存改变状态时,这种情况就会继续
下去。类似地,当多个PAGE_READWRITE的已提交页中的一个被改变成PAGE_READONLY保护
时,该区域也被分成多个较小的区域。

 

总结

在Win32中的虚拟内存管理函数提供在Windows NT中直接管理虚拟内存的能力。每个进程
的2 GB用户地址空间被分成为保留的、已提交的或者自由的虚拟地址内存区。一个区被
定义为一个连续的地址范围,其保护、类型和每个地址的基本分配是相同的,在每个区
中是一个或多个地址页,也可携带保护和页锁定标志状态位。


虚拟内存管理函数为应用程序提供了转换虚拟地址空间页状态的能力。一个应用程序可
以把内存类型从已提交的改变为保留的,或把保护模式从 PAGE_READWRITE 改变为
PAGE_READONLY,从而防止对某段地址空间的访问。一个应用程序可以锁定一页内存到工
作组,使得一个进程最少地分页关键内存页。虚拟内存函数被认为是低级函数,意味着
它们的速度相对较快,但是缺乏很多高级函数所具有的功能。







关于我们 - 购买方法 - 广告服务 - 网站地图 - 帮助信息 - 版权申明
Email:webmaster@ :233894 MSN:webmaster@
Phone:010-********
Copyright ©, Inc. All rights reserved.
苏ICP备05005475号




相关文档
最新文档