处理器在读取或写入内存位置时使用虚拟地址。 在这些作期间,处理器会将虚拟地址转换为物理地址。
使用虚拟地址访问内存有几个好处:
程序可以使用连续的虚拟地址范围来访问物理内存中的大型非连续内存缓冲区。
程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。 当物理内存不足时,内存管理器会将物理内存页(通常为 4 KB 大小)保存到磁盘文件中。 系统根据需要在物理内存和磁盘之间移动数据或代码页。
不同进程使用的虚拟地址是隔离的。 一个进程中的代码无法更改另一个进程或作系统正在使用的物理内存。
进程可用的虚拟地址范围称为进程的 虚拟地址空间。 每个用户 模式进程 都有自己的专用虚拟地址空间。
32 位进程通常具有 2 GB 范围内的虚拟地址空间,0x00000000到0x7FFFFFFF。
64 位 Windows 上的 64 位进程在 128 TB 范围内的虚拟地址空间从 0x000'00000000 到 0x7FFF'FFFFFFFF。
有时,一系列虚拟地址称为 虚拟内存范围。 有关详细信息,请参阅 内存和地址空间限制。
下图说明了虚拟地址空间的一些主要功能。
此图显示了两个 64 位进程的虚拟地址空间:Notepad.exe 和 MyApp.exe。 每个进程都有自己的虚拟地址空间,范围从 0x000'0000000 到 0x7FF'FFFFFFFF。 每个着色块表示虚拟或物理内存的一页(大小为 4 KB)。 记事本进程使用三个连续的虚拟地址页,从 0x7F7'93950000 开始。 但是,这三个连续的虚拟地址页映射到物理内存中的非连续页。 此外,这两个进程都使用从 0x7F7'93950000 开始的虚拟内存页,但这些虚拟页映射到不同的物理内存页。
用户空间和系统空间
Notepad.exe 和 MyApp.exe 等进程在用户模式下运行。 核心操作系统组件和许多驱动程序在特权更高的内核模式下运行。 有关处理器模式的详细信息,请参阅 用户模式和内核模式。
每个用户模式进程都有自己的专用虚拟地址空间,但在内核模式下运行的所有代码共享名为 系统空间的单个虚拟地址空间。 用户模式进程的虚拟地址空间称为 用户空间。
在 32 位 Windows 中,可用虚拟地址空间总数为 2^32 字节(4 GB)。 通常,较低的 2 GB 用于用户空间,而高 2 GB 用于系统空间。
在 32 位 Windows 中,可以指定(在启动时)可用的用户地址空间超过 2 GB。 但是,这意味着系统空间可用的虚拟地址更少。 可以将用户空间的大小增加到 3 GB,仅保留 1 GB 的系统空间。 若要增加用户空间的大小,请使用 BCDEdit /set increaseuserva。
在 64 位 Windows 中,虚拟地址空间的理论量为 2^64 字节(16 字节),但实际只使用 16 字节范围的一小部分。
在用户模式下运行的代码可以访问用户空间,但不能访问系统空间。 此限制可防止用户模式代码读取或更改受保护的作系统数据结构。 在内核模式下运行的代码可以访问用户空间和系统空间。 也就是说,在内核模式下运行的代码可以访问当前用户模式进程的系统空间和虚拟地址空间。
直接读取或写入用户空间中地址时,在内核模式下运行的驱动程序必须小心。 以下方案说明了原因。
用户模式程序启动从设备读取某些数据的请求。 程序提供缓冲区的起始地址来接收数据。
在内核模式下运行的设备驱动程序例程启动读取作,并将控制权返回到其调用方。
稍后,设备会中断当前正在运行的线程,以指示读取作已完成。 内核模式驱动程序例程处理属于任意进程的此任意线程上的中断。
此时,驱动程序不得将数据写入步骤 1 中提供的用户模式程序的起始地址。 此地址位于启动请求的进程虚拟地址空间中,该地址可能与当前进程不同。
分页池和非分页池
在用户空间中,所有物理内存页都可以根据需要分页到磁盘文件。 在系统空间中,某些物理页面可以调出,而其他页面则无法调出。 系统空间有两个区域用于动态分配内存:分页池和非分页池。
在分页池中分配的内存可以根据需要分页到磁盘文件。 在非分页池中分配的内存永远不会被分页到磁盘文件中。