windows内存管理

32位平台下,CPU的寻址能力为4GB,PC中有些设备(如显卡)都提供自己的设备内存,这部分内存会映射到PC的物理内存上,也就是读写这段物理内存地址,其实是在读写设备内存地址,而不会读写物理内存地址。虽然提供了4GB的寻址能力,但是实际可能没有这么大的物理内存,这样就引入了虚拟内存。Windows的所有程序(包括Ring3和Ring0的程序)实际操作的都是虚拟内存。对虚拟内存的操作,最终都会变成对实际物理内存的操作。由于Windwos是个多任务操作系统,到此,我们碰到了几个问题:一是,虚拟内存和真实的物理内存如何对应转换?二是,同时运行的进程如何实现自己内存空间的保护,同时在必要是也能共享部分内存?三是,因为虚拟内存实际是使用了磁盘,那需要有个算法在内存中来调入调出。我们来一一解释上面的疑问。

在CPU中有个CR0的寄存器,这个32位的寄存器中的一个位(PG位)是负责告诉系统是否分页。Windwos在启动前将此位置1,即Windows允许分页。DDK中有个PAGE_SIZE宏记录分页的大小,一般为4KB。这样,虚拟内存会被分割成1M个分页单元。其中部分单元会和物理内存对应起来。如虚拟内存中的第N个分页单元对应着物理内存第M个分页单元。这是多对一的映射,多个虚拟内存页可以映射同一个物理内存页。还有一部分单元会以文件的形式映射到磁盘上,并标记位脏(dirty)。读取这段虚拟内存时,系统会发出异常,触发异常处理函数,异常处理函数将这个页的磁盘文件读入内存,并将其标记位不脏。还有一部分的单元什么也不对应,即空的。有些物理既映射到进程1,也映射到进程2,这样修改进程2的那段虚拟内存也就修改了进程1上的那段虚拟内存,这种方法达到了进程间的内存共享。

虚拟地址在0~0X7FFFFFFF范围内的虚拟内存,即低2GB的虚拟地址,是用户模式地址,用户态(Ring3)程序只能访问这段地址。而0X80000000~0XFFFFFFFF范围的虚拟地址,即高2GB的虚拟地址,是内核模式地址。运行在内核态(Ring0)的程序能访问整个4GB的地址空间。Windows的核心代码和Windows的驱动程序加载的位置都在高2GB的内核地址中。同时,Windows操作系统在进行进程切换时,保持内核模式地址是完全相同的,只改变用户模式地址的映射。

驱动程序可以看成是一个特殊的DLL文件被应用程序加载到虚拟内存中,只不过加载地址是内核模式地址,而不是用户模式地址。它能访问的只是这个进程的虚拟内存,而不能是其他进程的虚拟地址空间。Windows驱动程序里的不同例程运行在不同的进程中。DriverEntry例程和AddDevice例程是运行在系统(System)进程中的。而其他一些例程,如IRP_MJ_READ等派遣函数会运行在某个进程环境中,所能访问的虚拟地址是这个进程的虚拟地址。

你可能感兴趣的:(windows内存管理)