13.1 Windows的虚拟地址空间安排
13.1.1虚拟地址空间的分区(即虚拟地址空间布局)
进程的地址空间划分
分区 |
x86 32位 Windows |
3GB用户模式下的x86 32位Windows |
X64 64位 Windows |
IA-64 64位 Windows |
空指针赋值区 |
0x0000 0000 0x0000 FFFF |
0x0000 0000 0x0000 FFFF |
0x00000000 00000000 0x00000000 0000FFFF |
0x00000000 00000000 0x00000000 0000FFFF |
用户模式分区 |
0x0001 0000 0x7FFE FFFF |
0x0001 0000 0xBFFE FFFF |
0x00000000 00010000 0x000007FF FFFEFFFF |
0x00000000 00010000 0x000006FB FFFEFFFF |
64KB禁入分区 |
0x7FFF 0000 0x7FFF FFFF |
0xBFFF 0000 0xBFFF FFFF |
0x000007FF FFFF0000 0x000007FF FFFFFFFF |
0x000006FB FFFF0000 0x000006FB FFFFFFFF |
内核模式 |
0x8000 0000 0xFFFF FFFF |
0xC000 0000 0xFFFF FFFF |
0x00000800 00000000 0xFFFFFFFF FFFFFFFF |
0x000006FC 00000000 0xFFFFFFFF FFFFFFFF |
(1)空指针赋值分区
①为帮助程序员捕获对空指针的赋值,当线程试图读取或写入这一分区的内存地址,就会引发访问违规
②没有任何办法可以让我们分配到位于这一地址区间的虚拟内存。
(2)用户模式分区
①进程地址空间的驻地。对于应用程序来说,大部分数据都保存在这一分区。
②32位下,默认为2GB大小。打开/3GB开关时,可扩大到3GB空间,但同时内核空间缩小为1GB)
【x86 Windows下获得更大的用户模式分区】——修改Windows启动配置数据(Boot Configuration Data,BCD)
①运行BCDEdit.exe
②bcdedit /set IncreaseUserVa 3072,就可以为进程保留3GB用户模式地址空间,IncreaseUserVa可接受的最小值为2048,即默认的2GB。取消的话:bcdedit /deletevalue IncreaseUserVa。
③为了让应用程序可以访问2GB以上的地址空间(特别地,早期的应用程序是不允许这样做的)。在链接时,可以打开/LARGEADDRESSAWARE链接开关。
【在64位Windows下得到2GB用户模式分区】将32位应用程序移植到64位环境下
①因大量使用32位指针开发程序,仅重新编译程序会导致指针截断错误和不正确的内存访问。但可以让应用程序在地址空间沙箱(Address space sandbox)中运行,这也是默认的情况,系统能够保证高33位都为0的64地址截断为32位,这样进程可用的地址空间就被限制在最底部的2GB中。
②当运行64位应用程序时,默认下系统会保留用户模式地址空间中在2GB以下(即最底部的2GB),这就是所谓的地址空间沙箱。这空间对于大多数的应用程序来说是足够的。
③为了让64位应用程序能够访问整个用户地址空间,必须指定/LARGEADDRESSAWARE链接器开关来链接应用程序。
(3)内核模式分区
操作系统代码的驻地。与线程调度、内存管理 、文件系统支持、网络支持以及设备驱动程序相关的代码都载入到这个分区中。该分区中的所有代码和数据都为所有进程共有,但这些代码和数据都是被保护起来的,如果试图在这分区的某个内存地址读取或写入数据时,会引发访问违规。
13.1.2 Windows内存安排(时间上的安排)
(1)每个应用程序都有自己的4GB寻址空间。该空间可存放操作系统、系统DLL和用户DLL代码,它们之中有各种函数供应用程序调用。再除去其他的一些空间,余下的是应用程序的代码、数据和可以分配的地址空间。
(2)不同应用程序的线性地址空间是隔离的。虽然它们在物理内存中同时存在,但在某个程序所属的时间片中,其他应用程序的代码和数据没有被映射到可寻址的线性地址中,所以是不可访问的。从编程的角度看,程序可供使用的4GB的寻址空间,而且这个空间是“私有的”
(3)DLL程序没有自己的“私有”的空间。它们总是被映射到其他应用程序的地址空间中,当做其他应用程序的一部分运行。原因很简单,如果它不和其他程序同属一个地址空间,应用程序就不能调用它。
(4)操作系统和系统DLL的代码需要供每个应用程序调用,所以在所有的时间片中都必须被映射;
(5)用户程序只在自己所属的时间片内被映射。用户DLL则有选择地被映射。如程序B和C都调用了xxx.dll,那么物理内存中xxx.dll(注意在内存中已经存在了!)的代码在图中的时间片2和n中被映射,其他时间片就不需要被映射。(当然物理内存中只需要一份xxx.dll的代码)。
原文:http://www.cnblogs.com/5iedu/p/4846223.html