SQL Server 2005 联机丛书(2007 年 9 月)
为 SQL Server 启用 AWE 内存
地址窗口化扩展插件 (AWE) 可以使 32 位操作系统访问大量内存。AWE 由操作系统提供,并且在 Microsoft Windows 2000 Server 和 Windows Server 2003 中的实现方式稍有不同。可以使用 awe enabled 选项启用 AWE。
在 Windows 2000 Server 中使用 AWE 映射内存
运行在 Windows 2000 上的 Microsoft SQL Server 2005 实例在 SQL Server 启动过程中根据下列事件顺序分配内存:
• 如果可用物理内存小于用户模式虚拟地址空间,则无法激活 AWE。在此情况下,SQL Server 将以非 AWE 模式运行,而不管 awe enabled 选项的设置情况。
• 如果可用物理内存大于用户模式虚拟地址空间,则可以激活 AWE。
o 如果可用物理内存大于 max server memory 选项的值,SQL Server 实例会锁定 max server memory 中指定的内存量。
o 如果可用物理内存小于 max server memory 选项的值或如果尚未设置 max server memory 选项,SQL Server 实例只留下 256 兆字节 (MB),而锁定所有其余的可用内存。
• AWE 映射内存一经分配便无法释放,除非关闭 SQL Server。
配置内存选项
极力建议每次启用 AWE 时都为 max server memory 设置一个值。如果 awe enabled 设置为 1(并且可用物理内存大于用户模式进程空间),则启动服务器后,运行在 Windows 2000 中的 SQL Server 2005 实例将锁定几乎所有的可用内存(或 max server memory 的值指定的内存,如果设置了此选项的话)。如果尚未设置 max server memory,则其他应用程序或 SQL Server 实例的可用物理内存将小于 128 MB。
无法将 AWE 映射内存池换出到分页系统文件。如果需要使用额外物理内存,Windows 必须换出其他应用程序,这样做可能会影响那些应用程序的性能。
若不想影响其他应用程序的性能,请配置 max server memory 留出一些额外可用内存以备其他应用程序和操作系统的不时之需。可以通过了解计算机上使用的所有其他应用程序启动之后还有多少内存可用,来确定可安全分配给 SQL Server 实例的内存量。
注意:
在 Windows 2000 Server 中,SQL Server AWE 将忽略 min server memory。
使用 SQL Server 性能监视器 Total Server Memory (KB) 计数器可以确定在 AWE 模式下运行的 SQL Server 实例所分配的内存量,也可以从 sysperfinfo 中选择内存使用量来确定实例所分配的内存量。
有关详细信息,请参阅监视内存使用量。
使用 AWE 运行 SQL Server 的多个实例
如果服务器运行的是 Windows 2000,则每个实例都应设置 max server memory。由于 Windows 2000 操作系统上运行的 SQL Server 2005 不支持动态分配 AWE 映射内存,因此,建议为每个实例都设置 max server memory 选项。
所有实例的 max server memory 值的总和应小于计算机的总物理内存。如果总和大于总物理内存,某些实例或者不会启动,或者所使用的内存小于 max server memory 设置所指定的内存量。例如,假设某台计算机有 16 GB 的物理内存,并且在该计算机上安装了三个 SQL Server 2005 实例。并且,每个实例的 max server memory 设置为 8 GB。如果您停止并重新启动所有三个实例,内存分配会如下所示:
1. 第一个实例使用 8 GB 的物理内存。
2. 第二个实例将启动,但使用的物理内存将略低于 8 GB(最多减少 128 MB)。
3. 第三个实例以动态内存模式启动并且使用 256 MB 的物理内存或更少的物理内存。
有关详细信息,请参阅管理大型数据库的内存。
在 Windows Server 2003 中使用 AWE 映射内存
在 Windows Server 2003 中,SQL Server 2005 支持动态分配 AWE 内存。启动过程中,SQL Server 仅保留一小部分 AWE 映射内存。当需要额外的 AWE 映射内存时,操作系统便会将其动态分配给 SQL Server。同样,如果所需的资源较少,则 SQL Server 可将 AWE 映射内存返回到操作系统,以供其他进程或应用程序使用。有关 awe enabled 配置选项的详细信息,请参阅 awe enabled 选项。
Windows Server 2003 系列所支持的物理内存量有所增加。AWE 可使用的物理内存取决于您所使用的操作系统。下面的列表列出了写入时每个 Windows Server 2003 操作系统版本可以使用的最大物理内存。
• Windows Server 2003 Standard Edition 最高支持 4 GB 的物理内存。
• Windows Server 2003 Enterprise Edition 最高支持 32 GB 的物理内存。
• Windows Server 2003 Datacenter Edition 最高支持 64 GB 的物理内存。
配置内存选项
SQL Server 2005 在任何 Windows Server 2003 操作系统版本上运行时,都会动态地分配 AWE 映射内存。换言之,缓冲池可以动态管理 AWE 映射内存(在 min server memory 和 max server memory 选项的约束内),以按照总体系统要求平衡 SQL Server 内存的使用。
启用 AWE 后,SQL Server 2005 将始终尝试使用 AWE 映射内存。这适用于所有内存配置,包括配置以提供给应用程序低于 3 GB 用户模式地址空间的计算机。
• 建议将 AWE 设为在 Windows Server 2003 上运行的 SQL Server 2005 的默认内存模式。热添加内存功能要求在启动 SQL Server 过程中启用 AWE。有关信息,请参阅热添加内存。
注意:
64 位操作系统上不需要 AWE,也不能在该系统上配置 AWE。
• 由于所支持的 AWE 映射内存容量在 3 GB 以下,因此,可在物理内存范围内定义 min server memory 和 max server memory 的值,或使用这两个选项的默认值。
• 可以考虑设置 SQL Server 的 max server memory 以保证其他内存能用于运行在计算机上的其他应用程序。虽然 SQL Server 可动态释放 AWE 映射内存,但当前已分配的 AWE 映射内存量无法换出页面文件。
若要使 SQL Server 2005 实例能够使用 AWE,请使用 sp_configure 将 awe enabled 选项设置为 1,然后重新启动 SQL Server。
有关 min server memory 和 max server memory 的详细信息,请参阅服务器内存选项。
在启用 AWE 之前,必须先配置“锁定内存页”策略。有关详细信息,请参阅如何启用“锁定内存中的页”选项 (Windows)。
示例
下面的示例显示如何激活 AWE 以及如何为 min server memory 配置 1 GB 的限制,为 max server memory 配置 6 GB 的限制。
首先,配置 AWE:
复制代码
sp_configure 'show advanced options', 1
RECONFIGURE
GO
sp_configure 'awe enabled', 1
RECONFIGURE
GO
重新启动 SQL Server 之后,会将以下消息写入 SQL Server 错误日志中:“已启用地址窗口化扩展插件。”
然后,配置内存:
复制代码
sp_configure 'min server memory', 1024
RECONFIGURE
GO
sp_configure 'max server memory', 6144
RECONFIGURE
GO
在此示例中,内存设置引导缓冲池在 1 GB 和 6 GB 之间动态管理 AWE 映射内存。如果其他应用程序需要额外的内存,则 SQL Server 可释放不再需要的已分配 AWE 映射内存。在此示例中,AWE 映射内存最多只能释放 1 GB。
如果将额外的内存添加到支持热添加内存的计算机中,则 SQL Server 也可以使用动态 AWE 内存来增加内存。热添加内存可用于 Windows Server 2003 Enterprise Edition 和 Datacenter Edition,允许计算机在运行时添加内存。例如,假设在具有 16 GB 物理内存的计算机上启动在 Windows Server 2003 Enterprise Edition 上运行的 SQL Server 2005。将操作系统配置为限制应用程序可使用 2 GB 的虚拟内存地址空间;并且已在 SQL Server 上激活 AWE。稍后,在计算机运行时系统管理员要添加 16 GB 的内存。SQL Server 2005 会立即识别添加的内存,并且,如有必要,可以利用这些内存。
有关使用 AWE 的详细信息,请参阅 Windows Server 2003 文档。
使用 AWE 运行 SQL Server 的多个实例
如果在同一台计算机上运行多个 SQL Server 2005 实例,并且每个实例都使用 AWE 映射内存,则应确保这些实例均按预期方式执行。
如果服务器运行的是 Windows Server 2003,则每个实例都应设置 min server memory。由于在 Windows Server 2003 上运行的 SQL Server 2005 支持动态 AWE 映射内存管理,因此,建议为每个实例都设置 min server memory 选项。由于 AWE 映射内存无法换出页面文件,因此,所有实例的 min server memory 值的总和应小于计算机上的物理总内存。
启动时,min server memory 选项不会强制 SQL Server 获取最小量的内存。基于数据库工作负荷按需分配内存。但是,达到 min server memory 阈值后,如果 SQL Server 为自己保留的内存小于该量,则 SQL Server 将不释放内存。因此,若要确保每个实例所分配的内存至少等于 min server memory 值,建议您启动后立即执行数据库服务器加载。服务器正常运行时,每一实例的可用内存会随时变化,但决不会小于 min server memory 值。
可以设置 max server memory 或将该选项保留为默认设置。将 max server memory 保留为默认值将导致 SQL Server 实例为争夺内存而竞争。
一起使用 AWE 和故障转移群集
如果使用的是 SQL Server 2005 故障转移群集和 AWE 内存,则必须确保所有实例的 max server memory 设置的总和小于故障转移群集中任一服务器上可用的最小物理内存。如果故障转移节点的物理内存比原节点上的内存小,则 SQL Server 2005 实例可能无法启动,或者可能在内存比在原节点上的内存小的情况下启动。
请参阅
任务
如何配置 awe enabled 选项 (SQL Server Management Studio)
概念
使用 AWE
管理大型数据库的内存
###################################################################
######################
配置 SQL Server 以便使用 2 GB 以上的物理内存(包括SQL Server 2005)
1.概要
使用Windows 2000 Server 的操作系统,对于SQL Server而言,需要打开操作系统的3G开关,它才能利用到2G以上的物理内存,否则这些4G以上内存只有2G能够被SQL Server使用到。
如果服务器上的内存高于4G,请打开操作系统的/3G开关。这样重新启动后,SQL Server将会自动利用大内存来提升数据库的性能,而不再受到2G的内存使用限制!
使用Windows 2000 Advanced Server、Windows 2000 Datacenter 或 Windows Server 2003如果使用 Boot.ini 的 /PAE 开关和 AWE 启用选项SQL Server 2000 就可以使用4G以上内存。
2.支持的操作系统版本
Windows 2000 Server
通常情况下,SQL Server 2000 Enterprise Edition 和 SQL Server 2000 Developer Edition 最多可以使用 2 GB 的物理内存。如果使用 AWE 启用选项,SQL Server 最多可以使用 4 GB 的物理内存。
由于在 Microsoft Windows 2000 Server 上不能使用“物理地址扩展”(PAE),因此无法为 Windows 2000 Server 上的应用程序分配 4 GB 以上的物理内存。
注意:此外,Windows 2000 Server 不能在 Boot.ini 文件中使用 3 GB 开关;
不过,Microsoft Windows 2000 Advanced Server 或 Microsoft Windows Datacenter 版本却可以在 Boot.ini 文件中使用 3 GB 开关。
Windows 2000 Advanced Server、Windows 2000 Datacenter 或 Windows Server 2003
32 位寻址模式可以提供的最大物理内存量为 4 GB。所有基于 IA-32 结构的处理器(从 Intel Pentium Pro 开始)都支持一种新的 36 位物理寻址模式,称为“物理地址扩展”(PAE)。PAE 允许 Windows 2000 Advanced Server 上最多使用 8 GB 的物理内存,允许 Windows 2000 Datacenter Server 上最多使用 32 GB 的物理内存。这是因为,根据测试,Windows 2000 Datacenter Server 上的内存限制为 32 GB。PAE 模式内核需要 Intel 结构的处理器 Pentium Pro(或更高性能的处理器),以及 Windows 2000 Advanced Server 或 Windows 2000 Datacenter。
Windows Server 2003 上支持的最大内存为 4 GB。但是,Windows Server 2003 Enterprise Edition 支持 32 GB 的物理 RAM。使用物理地址扩展 (PAE) 功能,Windows Server 2003 Datacenter Edition 可支持 64 GB 的物理内存。
对于下列系统,可以在 Boot.ini 文件中使用 3 GB 开关:
Microsoft Windows Server 2003、
Microsoft Windows Server 2003 Enterprise Edition 或 Microsoft Windows Server 2003 Datacenter Edition。
SQL Server 2000 Enterprise 和 SQL Server 2000 Developer Edition 都可以使用下列选项:
如果在 SQL Server 中使用 Boot.ini 的 /PAE 开关和 AWE 启用选项,SQL Server 2000 就可以使用 4 GB 以上的内存。没有 /PAE 开关,SQL Server 最多只能使用 3 GB 的内存。
在 Windows 2000 Data Center 上,要使 AWE 可以使用 16 GB 以上的内存,请确保在 Boot.ini 文件中没有使用 /3GB 开关。如果在 Boot.ini 文件中使用 /3GB 开关,Windows 2000 可能无法正常提供 16 GB 以上的任何内存。
所有 32 位应用程序都有 4 GB 的进程地址空间(32 位地址最多可以映射 4 GB 的内存)。如下图:
3.SQL Server 2000配置步骤
3.1. Windows 2000 Server 配置操作系统支持AWE
3.1.1. 修改BOOT.INI文件
我的电脑->C: (如下图)
3.1.2. 启用操作系统3GB开关
修改boot.ini文件,在启动windows项中添加 /3GB 参数。修改过后的boot.ini文件应该类似以下内容:
[boot loader]
timeout=8
default=multi(0)disk(0)rdisk(0)partition(1)
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)="Microsoft Windows 2000 Advanced Server" /3GB /fastdetect
3.1.3. 启用锁定内存页选项(windows)
启用锁定内存页选项
在"开始"菜单上单击"运行"子菜单,然后在"打开"框中键入"gpedit.msc"。
在"组策略"控制台上,展开"计算机配置",然后展开"Windows 设置"。
展开"安全设置",然后展开"本地策略"。
选择"用户权限分配"复选框。
详细资料窗格中随即显示出策略。
在详细资料窗格中,双击"锁定内存页"。
在"本地安全策略设置"对话框中,单击"添加"按钮。
在"选择用户或组"对话框中,添加有权运行 sqlservr.exe 的帐户。
3.1.4. 启用SQL Server 的AWE支持
下面的示例说明了如何启用 AWE 并为服务器内存最大值选项配置 3 GB 的限制:
sp_configure 'show advanced options', 1
RECONFIGURE
GO
sp_configure 'awe enabled', 1
RECONFIGURE
GO
sp_configure 'max server memory', 3072
RECONFIGURE
GO
3.1.5. 重新启动服务
为了支持 3 GB 的用户模式进程空间,必须将 /3gb 参数添加到 boot.ini 文件中并重新启动计算机,从而使 /3gb 参数生效。设置此参数后,用户应用程序线程可以寻址 3 GB 的进程地址空间,而为操作系统保留 1 GB 的进程地址空间。
3.2. Microsoft Windows Server 2003 Enterprise Edition 配置操作系统支持AWE
3.2.1. 修改BOOT.INI文件
我的电脑->C: (如下图)
3.2.2. 启用操作系统/PAE开关
如果在 SQL Server 中使用 Boot.ini 的 /PAE 开关和 AWE 启用选项,SQL Server 2000 就可以使用 4 GB 以上的内存。没有 /PAE 开关,SQL Server 最多只能使用 3 GB 的内存。
在 Windows 2000 Data Center 上,要使 AWE 可以使用 16 GB 以上的内存,请确保在 Boot.ini 文件中没有使用 /3GB 开关。如果在 Boot.ini 文件中使用 /3GB 开关,Windows 2000 可能无法正常提供 16 GB 以上的任何内存。
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Enterprise" /noexecute=optout /fastdetect /PAE
3.2.3. 启用锁定内存页选项(windows)
启用锁定内存页选项
在"开始"菜单上单击"运行"子菜单,然后在"打开"框中键入"gpedit.msc"。
在"组策略"控制台上,展开"计算机配置",然后展开"Windows 设置"。
展开"安全设置",然后展开"本地策略"。
选择"用户权限分配"复选框。
详细资料窗格中随即显示出策略。
在详细资料窗格中,双击"锁定内存页"。
在"本地安全策略设置"对话框中,单击"添加"按钮。
在"选择用户或组"对话框中,添加有权运行 sqlservr.exe 的帐户。
3.2.4. 启用SQL Server 的AWE支持
下面的示例说明了如何启用 AWE 并为服务器内存最大值选项配置 6 GB 的限制:
sp_configure 'show advanced options', 1
RECONFIGURE
GO
sp_configure 'awe enabled', 1
RECONFIGURE
GO
sp_configure 'max server memory', 6144
RECONFIGURE
GO
3.2.5. 重新启动服务
必须重新启动 SQL Server 2000 实例才能使更改生效。
net stop mssqlserver
net start mssqlserver
这样,SQL 服务启动后,就会把6G的内存给锁定,完全供SQL使用
4.SQL Server 2005配置步骤
4.1. 在Windows Server 2003使用SQL Server 2005概述
SQL Server 2005 支持在 Windows Server 2003 上动态分配 AWE 映射内存。通过允许访问超过在所配置虚拟内存地址空间上设置的限制的可用物理内存,AWE 可扩展 32 位操作系统上运行的应用程序的功能。
启动过程中,SQL Server 仅保留一小部分 AWE 映射内存。需要额外的 AWE 映射内存时,操作系统会动态地将其分配给 SQL Server。同样,如果需要更少的资源,SQL Server 会将 AWE 映射内存返还给操作系统,以供其他进程或应用程序使用。SQL Server 和操作系统之间的这种平衡受到 min server memory 和 max server memory 参数的限制。
在 Windows Server 2003 中运行 SQL Server 2005 时,无需重新启动 SQL Server 实例,SQL Server 即可响应 max server memory 和 min server memory 配置选项的更改。
在 Windows Server 2003 下,如果服务器的物理内存小于虚拟内存地址空间上已配置的限制,则该服务器支持动态 AWE 映射内存。在这种情况下使用 AWE 不会对性能产生影响,但添加的物理内存超过虚拟内存地址限制时,可以在不重新启动服务器的情况下使用此物理内存。
4.2. 启用AWE
对于 Windows Server 2003,由于 AWE 映射内存管理是动态的,因此在启动过程中,只分配总可用物理内存的一小部分。
如果已成功启用此选项,当 SQL Server 2005 实例启动时,SQL Server 错误日志中将写入消息“Address Windowing Extensions enabled”。
必须在启用 AWE 之前为 SQL Server 帐户授予 LOCK PAGE IN MEMORY 权限。
awe enabled 选项是一个高级选项。如果使用 sp_configure 系统存储过程来更改该设置,则只有在 show advanced options 设置为 1 时才能更改 awe enabled。必须重新启动 SQL Server 实例,AWE 才会生效。
4.3. 启用锁定内存页选项(windows)
启用锁定内存页选项
在"开始"菜单上单击"运行"子菜单,然后在"打开"框中键入"gpedit.msc"。
在"组策略"控制台上,展开"计算机配置",然后展开"Windows 设置"。
展开"安全设置",然后展开"本地策略"。
选择"用户权限分配"复选框。
详细资料窗格中随即显示出策略。
在详细资料窗格中,双击"锁定内存页"。
在"本地安全策略设置"对话框中,单击"添加"按钮。
在"选择用户或组"对话框中,添加有权运行 sqlservr.exe 的帐户。
4.4. 启用SQL Server 2005的AWE支持
若要启用 AWE,请将 awe enabled 设置为 1。除非指定了 max server memory 的值,否则 SQL Server 将保留几乎所有可用内存,只留下 128 MB 或更少。
如果已成功启用该选项,则当 SQL Server 2000 实例启动时,SQL Server 错误日志中将出现"已启用地址窗口扩展"这条消息。
awe enabled 是高级选项。如果正在使用 sp_configure 系统存储过程更改该设置,则只有
当 show advanced options 设置为 1 时才能更改 awe enabled。
如下:设定SQL 使用6G的内存
sp_configure 'show advanced options', 1
RECONFIGURE
GO
sp_configure 'awe enabled', 1
RECONFIGURE
GO
sp_configure 'max server memory', 6144
RECONFIGURE
GO
4.5. 重新启动服务
必须重新启动 SQL Server 2005 实例才能使更改生效。
net stop mssqlserver
net start mssqlserver
这样,SQL 服务启动后,就会把6G的内存给锁定,完全供SQL使用
自己可以写一个C程序不断的分配内存,用下面的方法:办法1:就是上面的朋友提过的 通过 /3GB或者/USERVA开关。
boot.ini 里头加上这个开关,系统会让出1G给应用程序访问。系统自己只用1G。这样子不是什么好办法。微软临时的方案而已。应用程序link时加上 LARGEADDRESSAWARE,在生成EXE的时候设置一个标志位,这个位系统看到了就让你访问 3G的空间(但是内存+页交换太小,你分配一样会失败).
/3GB指定3G,/USERVA指定一个值,不是死的3G.
办法2:通过AWE (Address Window Extension),地址窗扩展
窗?是的,窗。你可以人认为是一个buffer,用来作为中间物,给2边的东西倒腾。
socket接受发送数据也有窗的概念,一样的。
要细看AWE,你到MSDN上查关键是AWE或者Address Window Extension。Google上Goole一把。你有了2G甚至更多的内存(啥机器都有,你不能怀疑一个32位系统装个20G内存会有问题吧?硬件可以做的)可以这么干。没有的话就别这么做了,没什么用.AWE的原理很简单,你在比如4G的物理内存上,分配的一片物理内存X, 你再分配的一片虚拟内存(地址空间)Y,把 X 和 Y 通过address window映射。你可以在这片虚拟内存里头访问4G的物理内存。最多访问多少要看你的参数设置了。
AllocateUserPhysicalPages分配物理内存, VirtualAlloc申请虚拟内存,MapUserPhysicalPages进行映射。没什么难的.MSDN有个sample做这个事情,看看吧! 这么多关键字了应该好查到了。代码我不贴了 ,占篇幅。
顺便说一下,内存文件映射并不把什么映射到(2~4G)这范围。它是进程共享数据的方式,并不是扩大内存的方式。不过如果你有个大硬盘,创建这么个映射来保存/修改数据也是可以的,这不要求大的内存。和内存没关系。
引言Windows的内存结构是深入理解Windows操作系统如何运作的最关键之所在,通过对内存结构的认识可清楚地了解诸如进程间数据的共享、对内存进行有效的管理等问题,从而能够在程序设计时使程序以更加有效的方式运行。Windows操作系统对内存的管理可采取多种不同的方式,其中虚拟内存的管理方式可用来管理大型的对象和结构数组。
在Windows系统中,任何一个进程都被赋予其自己的虚拟地址空间,该虚拟地址空间覆盖了一个相当大的范围,对于32位进程,其地址空间为232=4,294,967,296 Byte,这使得一个指针可以使用从0x00000000到0xFFFFFFFF的4GB范围之内的任何一个值。虽然每一个32位进程可使用4GB的地址空间,但并不意味着每一个进程实际拥有4GB的物理地址空间,该地址空间仅仅是一个虚拟地址空间,此虚拟地址空间只是内存地址的一个范围。进程实际可以得到的物理内存要远小于其虚拟地址空间。进程的虚拟地址空间是为每个进程所私有的,在进程内运行的线程对内存空间的访问都被限制在调用进程之内,而不能访问属于其他进程的内存空间。这样,在不同的进程中可以使用相同地址的指针来指向属于各自调用进程的内容而不会由此引起混乱。下面分别对虚拟内存的各具体技术进行介绍。
地址空间中区域的保留与释放
在进程创建之初并被赋予地址空间时,其虚拟地址空间尚未分配,处于空闲状态。这时地址空间内的内存是不能使用的,必须首先通过VirtualAlloc()函数来分配其内的各个区域,对其进行保留。VirtualAlloc()函数原型为:
LPVOID VirtualAlloc(
LPVOID lpAddress,
DWORD dwSize,
DWORD flAllocationType,
DWORD flProtect
)
其参数lpAddress包含一个内存地址,用于定义待分配区域的首地址。通常可将此参数设置为NULL,由系统通过搜索地址空间来决定满足条件的未保留地址空间。这时系统可从地址空间的任意位置处开始保留一个区域,而且还可以通过向参数flAllocationType设置MEM_TOP_DOWN标志来指明在尽可能高的地址上分配内存。如果不希望由系统自动完成对内存区域的分配而为lpAddress设定了内存地址(必须确保其始终位于进程的用户模式分区中,否则将会导致分配的失败),那么系统将在进行分配之前首先检查在该内存地址上是否存在足够大的未保留空间,如果存在一个足够大的空闲区域,那么系统将会保留此区域并返回此保留区域的虚拟地址,否则将导致分配的失败而返回NULL。这里需要特别指出的是,在指定lpAddress的内存地址时,必须确保是从一个分配粒度的边界处开始。
一般来说,在不同的CPU平台下分配粒度各不相同,但目前所有Windows环境下的CPU如x86、32位Alpha、64位Alpha以及IA-64等均是采用64KB的分配粒度。如果保留区域的起始地址没有遵循从64KB分配粒度的边界开始之一原则,系统将自动调整该地址到最接近的64K的倍数。例如,如果指定的lpAddress为0x00781022,那么此保留区域实际是从0x00780000开始分配的。参数dwSize指定了保留区域的大小。但是系统实际保留的区域大小必须是CPU页面大小的整数倍,如果指定的dwSize并非CPU页面的整数倍,系统将自动对其进行调整,使其达到与之最接近的页面大小整数倍。与分配粒度一样,对于不同的CPU平台其页面大小也是不一样的。在x86平台下,页面大小为4KB,在32位Alpah平台下,页面大小为8KB。在使用时可以通过GetSystemInfo()来决定当前主机的页面大小。参数flAllocationType和flProtect分别定义了分配类型和访问保护属性。由于VirtualAlloc()可用来保留一个区域也可以用来占用物理存储器,因此通过flAllocationType来指定当前要保留的是一个区域还是要占用物理存储器是意义的。其可能使用的内存分配类型有:
分配类型 类型说明
MEM_COMMIT 为特定的页面区域分配内存中或磁盘的页面文件中的物理存储
MEM_PHYSICAL 分配物理内存(仅用于地址窗口扩展内存)
MEM_RESERVE 保留进程的虚拟地址空间,而不分配任何物理存储。保留页面可通过继续调用VirtualAlloc()而被占用
MEM_RESET 指明在内存中由参数lpAddress和dwSize指定的数据无效
MEM_TOP_DOWN 在尽可能高的地址上分配内存(Windows 98忽略此标志)
MEM_WRITE_WATCH 必须与MEM_RESERVE一起指定,使系统跟踪那些被写入分配区域的页面(仅针对Windows 98)
分配成功完成后,即在进程的虚拟地址空间中保留了一个区域,可以对此区域中的内存进行保护权限许可范围内的访问。当不再需要访问此地址空间区域时,应释放此区域。由VirtualFree()负责完成。其函数原型为:
BOOL VirtualFree(
LPVOID lpAddress,
DWORD dwSize,
DWORD dwFreeType
)
其中,参数lpAddress为指向待释放页面区域的指针。如果参数dwFreeType指定了MEM_RELEASE,则lpAddress必须为页面区域被保留时由VirtualAlloc()所返回的基地址。参数dwSize指定了要释放的地址空间区域的大小,如果参数dwFreeType指定了MEM_RELEASE标志,则将dwSize设置为0,由系统计算在特定内存地址上的待释放区域的大小。参数dwFreeType为所执行的释放操作的类型,其可能的取值为MEM_RELEASE和MEM_DECOMMIT,其中MEM_RELEASE标志指明要释放指定的保留页面区域,MEM_DECOMMIT标志则对指定的占用页面区域进行占用的解除。如果VirtualFree()成功执行完成,将回收全部范围的已分配页面,此后如再对这些已释放页面区域内存的访问将引发内存访问异常。释放后的页面区域可供系统继续分配使用。
下面这段代码演示了由系统在进程的用户模式分区内保留一个64KB大小的区域,并将其释放的过程:
// 在地址空间中保留一个区域
LPBYTE bBuffer = (LPBYTE)VirtualAlloc(NULL, 65536, MEM_RESERVE, PAGE_READWRITE)
……
// 释放已保留的区域
VirtualFree(bBuffer, 0, MEM_RELEASE)
物理存储器的提交与回收
在地址空间中保留一个区域后,并不能直接对其进行使用,必须在把物理存储器提交给该区域后,才可以访问区域中的内存地址。在提交过程中,物理存储器是按页面边界和页面大小的块来进行提交的。若要为一个已保留的地址空间区域提交物理存储器,需要再次调用VirtualAlloc()函数,所不同的是在执行物理存储器的提交过程中需要指定flAllocationType参数为MEM_COMMIT标志,使用的保护属性与保留区域时所用保护属性一致。在提交时,可以将物理存储器提交给整个保留区域,也可以进行部分提交,由VirtualAlloc()函数的lpAddress参数和dwSize参数指明要将物理存储器提交到何处以及要提交多少物理存储器。
与保留区域的释放类似,当不再需要访问保留区域中被提交的物理存储器时,提交的物理存储器应得到及时的释放。该回收过程与保留区域的释放一样也是通过VirtualFree()函数来完成的。在调用时为VirtualFree()的dwFreeType参数指定MEM_DECOMMIT标志,并在参数lpAddress和dwSize中传递用来标识要解除的第一个页面的内存地址和要释放的字节数。此回收过程同样也是以页面为单位来进行的,将回收设定范围所涉及到的所有页面。下面这段代码演示了对先前保留区域的提交过程,并在使用完毕后将其回收:
// 在地址空间中保留一个区域
LPBYTE bBuffer = (LPBYTE)VirtualAlloc(NULL, 65536, MEM_RESERVE, PAGE_READWRITE)
// 提交物理存储器
VirtualAlloc(bBuffer, 65536, MEM_COMMIT, PAGE_READWRITE)
……
// 回收提交的物理存储器
VirtualFree(bBuffer, 65536, MEM_DECOMMIT)
// 释放已保留的区域
VirtualFree(bBuffer, 0, MEM_RELEASE)
由于未经提交的保留区域实际是无法使用的,因此在编程过程中允许通过一次VirtualAlloc()调用而完成对地址空间的区域保留及对保留区域的物理存储器的提交。相应的,回收、释放过程也可由一次VirtualFree()调用来实现。上述代码可按此方法改写为:
// 在地址空间中保留一个区域并提交物理存储器
LPBYTE bBuffer = (LPBYTE)VirtualAlloc(NULL, 65536, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)
……
// 释放已保留的区域并回收提交的物理存储器
VirtualFree(bBuffer, 0, MEM_RELEASE | MEM_DECOMMIT)
页文件的使用
在前面曾多次提到物理存储器,这里所说的物理存储器并不局限于计算机内存,还包括在磁盘空间上创建的页文件,其存储空间大小为计算机内存和页文件存储容量之和。由于通常情况下磁盘存储空间要远大于内存的存储空间,因此页文件的使用对于应用程序而言相当于透明的增加了其所能使用的内存容量。在使用时,由操作系统和CPU负责对页文件进行维护和协调。只有在应用程序需要时才临时将页文件中的数据加载到内存供应用程序访问之用,在使用完毕后再从内存交换回页文件。
进程中的线程在访问位于已提交物理存储器的保留区域的内存地址时,如果此地址指向的数据当前已存在于内存,CPU将直接将进程的虚拟地址映射为物理地址,并完成对数据的访问;如果此数据是存在于页文件中的,就要试图将此数据从页文件加载到内存。在进行此处理时,首先要检查内存中是否有可供使用的空闲页面,如果有就可以直接将数据加载到内存中的空闲页面,否则就要从内存中寻找一个暂不使用的可释放的页面并将数据加载到此页面。如果被释放页面中的数据仍为有效数据(即以后还会用到),就要先将此页面从内存写入到页文件。在数据加载到内存后,仍要在CPU将虚拟地址映射为物理地址后方可实现对数据的访问。与对物理存储器中数据的访问有所不同,在运行可执行程序时并不进行程序代码和数据的从磁盘文件到页文件的复制过程,而是在确定了程序的代码及其数据的大小后,由系统直接将可执行程序的映像用作程序的保留地址空间区域。这样的处理方式大大缩短了程序的启动时间,并可减小页文件的尺寸。
对内存的管理
使用虚拟内存技术将能够对内存进行管理。对当前内存状态的动态信息可通过GlobalMemoryStatus()函数来获取。GlobalMemoryStatus()的函数原型为:
VOID GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer)
其参数lpBuffer为一个指向内存状态结构MEMORYSTATUS的指针,而且要预先对该结构对象的数据成员进行初始化。MEMORYSTATUS结构定义如下:
typedef struct _MEMORYSTATUS {
DWORD dwLength// MEMORYSTATUS结构大小
DWORD dwMemoryLoad// 已使用内存所占的百分比
DWORD dwTotalPhys// 物理存储器的总字节数
DWORD dwAvailPhys// 空闲物理存储器的字节数
DWORD dwTotalPageFile// 页文件包含的最大字节数
DWORD dwAvailPageFile// 页文件可用字节数
DWORD dwTotalVirtual// 用户模式分区大小
DWORD dwAvailVirtual// 用户模式分区中空闲内存大小
} MEMORYSTATUS, *LPMEMORYSTATUS
下面这段代码通过设置一个定时器而每隔5秒更新一次当前系统对内存的使用情况:
// 设置定时器
SetTimer(0, 5000, NULL)
……
void CSample22Dlg::OnTimer(UINT nIDEvent)
{
// 获取当前内存使用状态
MEMORYSTATUS mst
GlobalMemoryStatus(&mst)
// 已使用内存所占的百分比
m_dwMemoryLoad = mst.dwMemoryLoad
// 物理存储器的总字节数
m_dwAvailPhys = mst.dwAvailPhys / 1024
// 空闲物理存储器的字节数
m_dwAvailPageFile = mst.dwAvailPageFile / 1024
// 页文件包含的最大字节数
m_dwAvailVirtual = mst.dwAvailVirtual / 1024
// 页文件可用字节数
m_dwTotalPageFile = mst.dwTotalPageFile / 1024
// 用户模式分区大小
m_dwTotalPhys = mst.dwTotalPhys / 1024
// 用户模式分区中空闲内存大小
m_dwTotalVirtual = mst.dwTotalVirtual / 1024
// 更新显示
UpdateData(FALSE)
CDialog::OnTimer(nIDEvent)
}
对内存的管理除了对当前内存的使用状态信息进行获取外,还经常需要获取有关进程的虚拟地址空间的状态信息。可由VirtualQuery()函数来进行查询,其原型声明如下:
DWORD VirtualQuery(
LPCVOID lpAddress, // 内存地址
PMEMORY_BASIC_INFORMATION lpBuffer, // 指向内存信息结构的指针
DWORD dwLength // 内存的大小
)
其中lpAddress参数为要查询的虚拟内存地址,该值将被调整到最近的页边界处。当前计算机的页面大小可通过GetSystemInfo()函数获取,该函数需要一个指向SYSTEM_INFO结构的指针作为参数,获取到的系统信息将填充在该数据结构对象中。下面这段代码通过对GetSystemInfo()的调用而获取了当前的系统信息:
// 得到当前系统信息
GetSystemInfo(&m_sin)
// 位屏蔽,指明哪个CPU是活动的
m_dwActiveProcessorMask = m_sin.dwActiveProcessorMask
// 保留的地址空间区域的分配粒度
m_dwAllocationGranularity = m_sin.dwAllocationGranularity
// 进程的可用地址空间的最小内存地址
m_dwMaxApplicationAddress = (DWORD)m_sin.lpMaximumApplicationAddress
// 进程的可用地址空间的最大内存地址
m_dwMinApplicationAddress = (DWORD)m_sin.lpMinimumApplicationAddress
// 计算机中CPU的数目
m_dwNumberOfProcessors = m_sin.dwNumberOfProcessors
// 页面大小
m_dwPageSize = m_sin.dwPageSize
// 处理器类型
m_dwProcessorType = m_sin.dwProcessorType
//进一步细分处理器级别
m_wProcessorLevel = m_sin.wProcessorLevel
// 系统处理器的结构
m_wProcessorArchitecture = m_sin.wProcessorArchitecture
// 更新显示
UpdateData(FALSE)
VirtualQuery()的第二个参数lpBuffer为一个指向MEMORY_BASIC_INFORMATION结构的指针。VirtualQuery()如成功执行,该结构对象中将保存查询到的虚拟地址空间状态信息。MEMORY_BASIC_INFORMATION结构的定义为:
typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress// 保留区域的基地址
PVOID AllocationBase// 分配的基地址
DWORD AllocationProtect// 初次保留时所设置的保护属性
DWORD RegionSize// 区域大小
DWORD State// 状态(提交、保留或空闲)
DWORD Protect// 当前访问保护属性
DWORD Type// 页面类型
} MEMORY_BASIC_INFORMATION
通过VirtualQuery()函数对由lpAddress和dwLength参数指定的虚拟地址空间区域的查询而获取得到的相关状态信息:
// 更新显示
UpdateData(TRUE)
// 虚拟地址空间状态结构
MEMORY_BASIC_INFORMATION mbi
// 查询指定虚拟地址空间的状态信息
VirtualQuery((LPCVOID)m_dwAddress, &mbi, 1024)
// 保留区域的基地址
m_dwBaseAddress = (DWORD)mbi.BaseAddress
// 分配的基地址
m_dwAllocateBase = (DWORD)mbi.AllocationBase
// 初次保留时所设置的保护属性
m_dwAllocateProtect = mbi.AllocationProtect
// 区域大小
m_dwRegionSize = mbi.RegionSize
// 状态(提交、保留或空闲)
m_dwState = mbi.State
// 当前访问保护属性
m_dwProtect = mbi.Protect
// 页面类型
m_dwType = mbi.Type
// 更新显示
UpdateData(FALSE)
小结
本文主要对内存管理中的虚拟内存技术的基本原理、使用方法和对内存的管理等进行了介绍。通过本文将能够掌握虚拟内存的一般使用方法,与之相关的内存管理技术还包括内存文件映射和堆管理等技术,读者可参阅相关文章。这几种内存管理技术同属Windows编程中的高级技术,在应用程序中适当使用将有助于程序性能的提高。本文所述程序在Windows 2000 Professional下由Microsoft Viusual C++ 6.0编译通过。
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)