网站已经改版为Wordpress版本,这里是旧版本的快照,请不要在页面中留言.

Windows 内存管理的一些点点滴滴


本文出自悠然品鉴,转载请注明出处:http://www.youranshare.com/blog/sid/70.html

对于一个鼓捣驱动的程序猿来说,就需要比其他的程序猿了解更多的Windows内部的内存管理机制,并且在开发驱动程序的时候更加有效的使用内存,因为驱动是在R0内核层次的开发,也就是说在平常的那些R3应用层次的运行时函数就不能使用了,取而代之的应该是DDK所提供的高效的内核函数,本文这里就简单的介绍一下有关windows内存管理的一些基本东西吧。

物理内存(Physical Memory Address)

物理内存嘛,当然是可以用手摸到的东西o(╯□╰)o,比如你的内存条,显卡内存神马的…

PC上一共有3条总线,分别是数据总线、地址总线和控制总线。对于一个32位的cpu来说,它的寻址能力为2的32次方个字节,也就是4GB。同样在你的PC上也会有很多设备,其中这些设备多多少少也会有一定的设备内存,比如显卡,他有自己的显卡显存。这一部分内存会映射到PC的物理内存上,也就是读写这段物理内存地址,其实会读写设备内存地址,而不是会读写物理内存地址。在很多情况下,也会广义的认为这也是物理内存地址。比如下图小悠的显卡的显存地址,对于一个设备可以有好几个块设备内存映射到物理内存上。

虚拟内存地址(Virtual Memory Address)

对于32位的CPU,虽然寻址范围为4GB,然而在PC中往往没有这么多的真实物理内存。因此操作系统和MMU(CPU内存管理单元)为使用者提供了虚拟内存的概念。在windows中的所有程序,包括R0内核的驱动程序可以直接操作的都是虚拟内存,之所以称之为虚拟是因为虽然这个地址只是逻辑上的地址,但是对它的操作最终会变成对实际物理地址的一系列操作。

 

    简单的说一下虚拟地址与实际物理地址的转换过程。在CPU中有一个重要的寄存器CR0,他是32位的寄存器,其中有一个PG位表示系统是否开启分页。Windows启动的时候会将PG位设置为1,开启系统分页,一般分页大小都是4KB,4GB的内存会被划分为4GB/4KB = 2^20(2的20次方)个分页单元。

 

   在这么多的分页单元中有一部分分页单元会和实际的物理内存地址对应起来,例如虚拟内存的第100号分页对应这个物理内存的第56号分页。注意这中对应关系是多对一的映射,多个虚拟内存分页可能会会对应同一个物理内存页,而且还有一些虚拟内存页不会映射到物理内存页上,而是被映射到了磁盘上的文件,并且会把这个虚拟内存页标记为“脏”,当读取到这个虚拟内存页的时候,操作系统会发出一个异常,并且触发异常处理函数,函数会把这个页所对应的磁盘文件读取到内存,并设置虚拟内存上的这个页为“不脏”;操作系统会把不经常读取的内存页交换到内存,设置其虚拟内存页为“脏”。还有一部分内存页什么也不对应,即是空的。
  

下面是小悠画了一个系统中两个运行的进程的虚拟内存映射物理内存的图:


    从图中可以看出,进程A和进程B的虚拟页映射的位置是不相同的,例如进程A的虚拟页4映射为物理分页的5,进程B的虚拟分页4映射为物理分页4,因此在进程2中的操作无论如何也是不会影响物理分页5的。另外可以看到物理内存页2、3、4是被AB两个进程都有映射,这样AB进程操作的时候都可以影响物理内存页2、3、4,这种情况是进程之间的共享内存,当然这是在windows操作系统的控制下的。除此之外还可看到有很多虚拟分页是没有对应的映射的。

 

Windows这样设计,主要是因为下面的两个原因:

使用虚拟内存增加了内存的大小(不是物理内存,只是让程序看来拥有了一个4GB的运行空间),不管PC是否拥有足够的4GB的物理内存,操作系统总是能有4GB的虚拟内存,这就能让程序能够申请更多的内存,当物理内存不够的时候,可以将不常用的虚拟内存页映射为磁盘上的文件,等需要的时候再从磁盘加载到内存。

虚拟内存使得每个进程都会拥有自己的4GB虚拟寻址空间,进程之间的4GB虚拟内存互不干扰,例如进程A中地址0x4000与进程B的0x4000他们的地址值一样,但是这个地址所在的虚拟页映射到物理内存上页的位置不一样,修改进程A的这个地址影响到物理内存对应的页,但是B进程对应的物理页与A不是同一个,这样一来A对B就没有任何影响了。

 

用户模式地址与内核模式的地址

每一个应用程序都会有一个对应的4GB虚拟地址空间,在这个4GB的虚拟地址空间中,0~0x7FFFFFFF范围的虚拟地址,也就是低2GB的虚拟地址被称为用户模式地址。而0x8000000~0xFFFFFFFF范围内的高2GB的虚拟地址被称为内核模式地址,在windows中规定:运行在用户泰(Ring3层)的程序只能访问用户模式地址,而运行在核心态(Ring0层)的程序可以访问整个4GB的虚拟地址,如下图所示:

 

   Windows的核心代码和Windows的驱动程序都是加载在高2GB的内核地址空间里的,所以一般的应用程序是没办法访问到这些位置的,这也就加强了系统的稳健性。与此同时操作系统在切换进程的时候只改变用户模式的低2GB虚拟地址映射,高2GB的虚拟地址映射不改变,也就是说所有进程的高2GB虚拟地址的映射都是相同的。

 


  • 标签:
  • 物理内存
  • 虚拟内存
  • 用户模式与内核模式
网站已经改版为Wordpress版本,这里是旧版本的快照,请不要在页面中留言.