深入SQL SERVER 2000的内存管理机制(二)

**

** 深入 ** ** SQL SERVER 2000 ** ** 的内存管理机制(二) ** ** **



** http://msdn.microsoft.com/data/default.aspx?pull=/library/en-us/dnsqldev/html/sqldev_01262004.asp **

**

** 可访问大地址的应用 ** ** (Large-Address-Aware Executables) **

在 Windows 增加支持 ** /3GB ** 参数以前 , 一个应用程序是无法访问一个带有高位设置的指针 . 一个 32 位的指针只有前 31 位地址空间可以被用户模式的应用程序访问 . 这剩余的一位不用 . 因此有一些聪明的开发者因为其他的目的不愿意在处理内存地址空间时浪费这一位 .( 举例来说 : 可以用来标志一个指针引用其它应用程序分配的数据类型 ). 这样就 ** /3GB ** 参数就遇到一个难题 , 因为这种类型的程序不能方便的区分一个合法的指针引用的内存空间在 2G 的分界线以上与一个内存地址空间在 2G 以下 , 但它的高位已经被用做它用的指针 . 基本上如果一台机器用 ** /3GB ** 的参数启动 , 这种应用程序是无法运行的 . 为解决这种状况 , 微软在 WIN32 的 ** PE ** 文件 Characteristics 字段增加了一个新的标志位来表示一个程序是否运行在 可访问大地址的 ** (Large-Address-Aware Executables) ** 模式 . 当该标志位被起用 ( IMAGE_FILE_LARGE_ADDRESS_AWARE ), 该可执行文件头部 Characteristics 字段的 32 位被置位 . 通过这个可执行文件头部的标志位 , 应用程序可以暗示 WINDOWS 它可以处理带有高位设置的指针 , 这样就不会带来任何异常结果 . 当该标志被置位并且支持这种方式启动的 Windows 也是通过 ** /3GB ** 的参数启动 , 这时操作系统会提供一直扩展的私有用户模式的地址空间给应用程序 . 你可以通过工具 , 比如 : DumpBin 和 ** ImageCfg ** ( 转储可执行文件的头部 ) 来检查一个可执行文件的该标志位 . Visual C++ 通过 ** /LARGEADDRESSAWARE ** 连接器开关来表示 ** IMAGE_FILE_LARGE_ADDRESS_AWARE ** , SQL SERVR 已经将该标志位激活 , 所以你可以在支持 ** /3GB ** 参数的 Windows 版本中使用该参数 , 这样操作系统回自动扩展 SQL SERVER 的用户内存空间 .

** 注释 ** ** : ** Windows 在可执行文件启动时检查 ** IMAGE_FILE_LARGE_ADDRESS_AWARE ** 标志位 , 但忽略 DLL 文件 .DLL 代码必须自动处理高位被置位的指针。

** 物理内存扩展 ** ** **

Intel 处理器自从 Pentium PRO 开始,以后的处理器都支持一种 物理内存扩展( ** PAE ** ** ) ** 的内存映射模式。 ** PAE ** 模式提供了可以访问 64GB 的物理内存空间。在 ** PAE ** 模式中,内存管理单元( ** Memory Management Unit (MMU) ** ) 仍然执行:页目录入口 ** page directory entries(PDEs) ** 和页表入口 ** page table entries (PTEs) ** , 但是在此之上有一个新的级别:页目录指针表。同时,在 ** PAE ** 模式 PDEs 和 PTEs 是 64 位的(不仅仅是标准的 32 位),这样系统可以映射比标准转换更多的内存空间,因为 PDEs 和 PTEs 模式的寻址宽度是标准的 2 倍。这并不仅仅是增加了页目录指针表。页目录指针表被用来管理这些大容量表和索引。一些特殊版本的 Windows 内核需要运行在 ** PAE ** 模式。这中内核集成在 Windows 2000 以及以后的版本中,在单处理器的机器中体现在 Ntkrnlpa.exe 文件中,在多处理器的机器中体现在 Ntkrnlpamp.exe 文件中。你可以向增加 ** /3GB ** 和 ** /USERVA ** 参数一样在 BOOT.INI 文件中加 ** /PAE ** 参数激活 ** PAE ** 模式。

** 地址窗口扩展 ** ** **

Windows 的地址窗口扩展( ** AWE ** )机制可以允许应用程序访问超过 4GB 的物理内存。一个 32 位的指针是一个整数,只能保存 0x00000000 到 0xFFFFFFFF 的值,就是说可以引用 4GB 以内线性的内存地址空间, ** AWE ** 允许一个应用程序绕过这些限制,通过操作系统访问所有的内存空间。

从概念上说, ** AWE ** 并不是一个新的事物。在计算机发展之初,操作系统和应用程序已经使用相似的机制回避指针的限制。例如:我们倒退到 DOS 年代, 32 位扩充功能被经常用来允许一个 16 位的程序访问他自已以外的内存地址空间。一些特殊目的管理者和 API 经常使用扩充内存和扩展内存。你可能记得这样一个很久以前产品 Quarterdeck QEMM-386 经常用来做这样的事情。典型的机制是允许一个指针可以访问超过本身限制的空间,(比如:地址太大无法在自己的指针中)通过在可以访问的地址空间分配一个窗口或区域来和本身无法访问的内存地址之间传递指针。 ** AWE ** 的工作原理:你可以在可以访问的地址空间提供一块区域(窗口)作为分段传输区,来传送在用户内存空间无法访问的内存地址。

为了使用 ** AWE ** ,一个应用程序需要:

1. 分配的物理内存地址可以通过 ** AllocateUserPhysicalPages ** API 函数访问。这个函数需要调用者有 ** Lock Pages in Memory ** 的权限。

2. 在可以访问的内存空间建立一块区域。通过 ** VirtualAlloc ** API 函数可以作为映射一个物理内存的映射窗口。

3. 通过 ** MapUserPhysicalPages ** 或 ** MapUserPhysicalPagesScatter ** WIN32 API 函数完成物理内存和虚拟内存的映射。

** AWE ** 已经存在于所有的 Windows 2000 和以后的操作系统中 , 甚至可以用于物理内存低于 2GB 的操作系统中,最典型的应用是在 2GB 或以上物理内存的机器上,因为这是一个 32 位处理器访问 3GB 以下内存空间的唯一方法。如果你在一个低于 3GB 物理内存的 SQL Server 系统中激活 ** AWE ** 支持,系统将忽略这个选项同时转换为虚拟内存管理器代替。 ** AWE ** 内存有一个有趣的特征就是从不和磁盘交换数据。你也许注意到特有的 ** AWE ** API 程序引用可以访问的内存空间是作为物理内存访问。这点确切的说就是: ** AWE ** 内存是不和系统的虚拟页面文件交互物理内存空间。

虚拟内存窗口被用来缓存 ** AWE ** 读写访问物理内存的请求。因此,当你配置这个窗口是 ** PAGE_READWRITE ** 唯一可以保护的特征就是转嫁给了 ** VirtualAlloc ** API 函数。不要惊奇,这也意味你不能用 ** VirtualProtect ** API 函数来保护这块内存区域的修改和访问。

** 注释 ** ** : ** 还没有专门的工具用来调查应用程序 ** AWE ** 内存使用(任务管理器,性能监视器和监视系统 等等),显示每一个程序 ** AWE ** 内存的使用数量。这样就没有每个程序使用 ** AWE ** 内存数量的轨迹,同时这些内存也没包括在每个的程序的工作内存集中。

** /3GB ** ** 和 ** ** AWE ** ** 比较 ** ** **

增加用户程序地址空间的能力几乎有 50 %的应用程序是通过内存调整,这是在 Windows 内存管理机制当中非常快捷和受欢迎的手段。而且 Windows AWE 内存机制也是非常灵活和稳定的。就像我前面所说的,当你增加 1G 的用户内存空间,这些内存是通过减少核心内存空间获得的(从 2G 减到 1G )。因为核心代码的运行对整个内存空间来说是很狭窄的一块即使用于 2G 的空间,收缩这些内存空间意味着内部核心架构也会收缩。其中最重要的是 windows 用来管理物理内存的表 , 当你收缩核心内存空间到 1G ,你就限制了这个表的大小,这样只能管理最大 16GB 的物理内存。例如:如果你的应用程序运行在有 64GB 物理内存的 SERVER 上并且你在启动时加了 ** /3GB ** 的参数。你只能访问整个内存的 25% 的空间 — 其余的 48GB 的内存空间无论时操作系统还是应用程序都无法访问。 ** AWE ** 可以允许你访问比加 ** /3GB ** 参数更高的内存空间。显然,你通过 ** /3GB ** 的参数只是增加了 1GB 的用户内存空间,这些增加的内存空间只是对那些大地址自动获得的应用程序有效,但是只有 1GB 。和 ** /3GB ** 参数对比, ** AWE ** 可以使整个的物理内存对操作系统有效和对使用 ** AWE ** WIN32 API 的应用程序有效。因此, ** AWE ** 使用和操作起来更加复杂,也更加灵活和可扩展。

着并不是说 ** /3GB ** 比 ** AWE ** 更好是不存在的-不过这确实存在,比如:如果你需要分配更多的内存空间,但不能在 ** AWE ** 中分配(线程堆栈,内存锁,过程计划),你也许发现 ** /3GB ** 回更好一些。

Published At
Categories with 数据库类
Tagged with
comments powered by Disqus