Hello! 欢迎来到小浪云!


Win32之内存管理之虚拟内存跟物理内存


一、虚拟内存与物理内存

我们知道,每个应用程序都拥有自己独立的4GB空间。例如,假设A进程在地址123处存储了值10,而B进程在地址123处存储了值20,这两个进程互不影响。然而,这些值是真实存在的,并且存储在物理内存中。如下图所示:

Win32之内存管理之虚拟内存跟物理内存

根据上图,我们可以区分虚拟内存和物理内存。如果我们修改了物理内存的值,那么会影响A进程或B进程。

当然,如果你学过内核驱动开发,就知道内核驱动读写正是这种机制。我也曾编写过一个简单的内核驱动读写程序,详情请查看内核驱动目录。

因此,虚拟内存是虚构的,只有在使用时才会映射到物理内存中。

二、物理内存的管理

物理内存是以4KB(即4096字节)的方式进行管理的,这一单位也称为一页。因此,在使用API时,我们经常会看到与页相关的操作,这是因为内存是以页为单位进行管理的。

如下图所示:

Win32之内存管理之虚拟内存跟物理内存

进程A的值被放置在物理页中。

传统上,进程拥有4GB的地址空间,但实际上分为高2GB和低2GB。高2GB由内核使用,因此用户只能使用低2GB。而低2GB中也有高低各64KB的部分是不可用的(如果学过内核,可以通过构造来使用)。

如下图所示:

Win32之内存管理之虚拟内存跟物理内存

用户模式可以使用的内存是橘黄色部分,但没有对应的物理页。只有当我们申请内存时,才会有对应的物理页。

如果想查看三环程序使用的物理页,可以通过双机调试来调试我们的程序,使用Windbg进行操作:

  1. 首先使用命令!Process遍历出我们程序的EXE地址。
  2. 使用dt EPROCESS遍历出的地址,得到这个应用程序的EPROCESS结构。
  3. 得到EPROCESS结构中偏移11c(即成员VadRoot)的地址,使用!VAD地址(EPROCESS + 地址)可以得出这个EXE使用的内存物理页。

如果你不会使用也没关系,观看下图:

Win32之内存管理之虚拟内存跟物理内存

此图说明了我们的线性地址从10开始到10结束。因为物理页是以4KB存储的,所以10代表的是1000,后面的大小是1000,因此下一个位置从20开始,即2000线性地址。

三、物理页大小

物理页的大小根据你的物理内存大小来设定。也就是说,你的物理内存有多大,就可以换算出物理页的数量。我们可以通过任务管理器查看物理页的总数。

例如,如下图所示:

Win32之内存管理之虚拟内存跟物理内存

我们换算一下,1048048 / 4转换为16进制就是可以有多少个物理页。例如,我们的例子中有3FF7C个物理页。

我们也可以使用Windbg通过dd命令查看,只需DD这个变量即可。

Win32之内存管理之虚拟内存跟物理内存

如果我们的物理页超过了,那么操作系统还支持使用硬盘来作为物理内存。

具体设置如下:

计算机属性 -> 高级系统设置 -> 高级 -> 性能设置 -> 高级 -> 虚拟内存更改。

Win32之内存管理之虚拟内存跟物理内存

这块内存会在Windows上保存,文件名为pagefile.sys,通常是c盘的隐藏文件。我们可以通过everything搜索找到它。

Win32之内存管理之虚拟内存跟物理内存

三、操作系统可识别内存

我们可用的内存是我们计算出的物理页大小加上虚拟内存的大小。然而,操作系统可识别的内存并不是这么大。

也就是说,即使我们增加了很多内存条,也不会有任何效果。

32位系统下最多能识别64GB内存,而WinXP只能识别4GB内存。具体知识需要学习Windows内核中的页表(PTE、PDE)、页目录表等才能清楚,这里就不多说了,只需了解即可。

相关阅读