Windows 虚拟内存简介

虚拟内存提供了一个内存的逻辑视图,它并不对应于物理内存的布局。在运行的时候,内存管理器借助于硬件的支持,将虚拟地址映射成物理地址。

每个进程都有自己的虚拟地址空间,而且它会感觉到自己独占了这个很大的地址空间。在 32 位 x86 系统中,总的虚拟地址空间的大小为 4GB。因为 32 位指针可以表示 0X00000000 到 0XFFFFFFFF 之间的值。但是默认情况下,Windows 会将 2GB 的地址空间给进程,作为其私有地址空间,称为用户模式空间;而另一半(地址空间中较高的一半,从 0X80000000 到 0XFFFFFFFF)则用做它自己的受保护的内核使用,称为内核模式空间。

虚拟内存有三个好处:

  • 程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的内存块。
  • 程序可以访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为 4 KB)保存到磁盘文件。页面会根据需要在物理内存与磁盘之间换入换出。
  • 不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法访问正在由另一进程使用的物理内存。

应用程序有三种使用内存方法:

  1. 以页为单位的虚拟内存分配方法,适合于大型对象或结构数组;
  2. 内存映射文件方法,适合于大型数据流文件以及多个进程之间的数据共享;
  3. 内存堆方法,适合于大量的小型内存申请。

有一系列的 Win32 API 可以用来进行内存相关的分配、使用、查询操作,详细内容可以查询微软的文档。下面主要介绍第一类方法。

Windows 进程虚地址空间中的页有 3 种状态:自由(free),预留(reserved),提交(committed)。进程还可以对某一页进行锁定(lock)与解锁(unlock),被锁定的内存会有极大概率被保留在物理内存中(不能保证)。状态间的相互关系如下图:

Win32 memory

Windows 可以对内存设置保护类型,实验中用到的几个列举如下:

宏定义类型
PAGE_READONLY只读
PAGE_READWRITE读写
PAGE_EXECUTE执行
PAGE_EXECUTE_READ写+执行
PAGE_EXECUTE_READWRITE读写+执行

对一个页执行权限以外的操作会引发错误。