Windows xp/Vista/Linux的内核映射以及内存置换算法

晨曦之光 发布于 2012/04/10 15:06
阅读 335
收藏 0

linux的内存管理我认为是高效的,windows xp的我认为是豪华的,vista的呢?我认为是无以伦比的(理论是无以伦比,但是实际上不是那样)。
  linux把内核的主要数据结构映射到内核空间3g到3g+768的空间内,在系统初始化的时候就将物理内存的前896页映射到内核的3g到3g+896 的地址空间,这内部的内存是一一对应的,而且在进程创建之初,此进程的pgd是在slab分配的,而slab属于物理内存映射区,所以进程的pgd是属于 物理内存映射区的,与物理内存是一一对应的。在linux中,进程的pgd是随时分配的,在要创建新的进程的时候,就会为该进程分配pgd,该pdg映射 到的 虚拟内存就会该分配到的pgd的物理内存加上0xc0000000,因为物理内存是从伙伴系统随即分配的,因此虚拟内存也就是随即的(加上 0xc0000000)。
linux在系统启动之初,就会将所有小于896m的物理内存意一一映射到内核空间,建立相关页表,并且将几乎所有内存加入伙伴系统。当内核使用内核数据结构的时候,就会从伙伴系统把内存页面拽出来,页表还是原来的页表;在以后用户进程需要内存页面的时候,操作系统仍然会从伙伴系统分配页面,但是不会和已 经使用的内核数据使用的页面冲突,因为当时那些内核数据页面已经不再伙伴系统了。这样用户进程顺利的得到页面,然后映射到对应进程的虚拟地址空间,但是这个时候,原来在系统初始化的时候建立的一一对应的页表(如果小与896的话)还没有清除。实际上这是没有必要清除的,因为那毕竟是内核映射的页面,什么时候都不过分,它将永远存在(按照道理说也是这样,内核为每一个页面保持一个映射难道不应该吗?以后会看到windows也是这么做的)。所以说,在 linux中,低于896m的内存中的每个页面最少有一个映射,就是内核映射,加上如果有用户进程映射就不计其数了。
在windows中,内核的映射需要遵循更多的规则,我实在想不明白这是什么理由,就像欧洲出席高档舞会男士必须穿燕尾服那样不可理解。每个进程的页表必须影射到固定的0xC0300000开始的4k区域内,而且,所有物理内存小于512m的物理内存区域必须映射到内核空间固定的0x80000000 - 0x9FFFFFFF虚拟地址内,这样,大多数的小于512的物理内存都有两个映射,一个映射到0x80000000 - 0x9FFFFFFF区域,一个到实际的映射区域,这是否说明大量的内存映射冗余,不得而知,但是我就是觉得windows的内存映射很商业化,而 linux的很艺术,实际上,内核保留一个物理内存的拷贝是应该的。linux和windows都是将物理内存的一部分一一映射到内核地址空间,区别在于:1.linux的冗余比较少;2.linux的页表映射不是固定的,而windows是固定的。在window中,为了节省4k的内存空间,采用了自 映射的技术,就是说,页目录同时也当页表使用,因为页目录被固定映射到内核的0xC0300000之 处,那么页目录的768项也指向页目录的物理地址之处,它之所以可以实现是因为页目录的映射是固定的,在linux中并没有实现自映射技术,因为 linux中页目录项的768项以上是相同的(在windows中0x80000000以上有几项是不同的,其中之一就是768项),它们是在slab的 构造函数里面初始化的,所以,因为页目录的不固定,实现自映射是不容易的,实际上,修改一下几个页目录就可以了,但是linux的设计者认为这不值得。可 以看出,linux并不吝啬那么一点点内存的,它更适合大型服务器,而windows却那么的规整,我实在看不出来这到底有什么必要,再一个,这个自映射 之所以可以实现,完全在于x86平台上,页目录项和页表项的结构是一致的,而windows主要针对x86,但是linux面对的是多平台,它绝对不能寄 希望于页目录项和页表项结构的等同。
  windows将页表连续映射到0xc0000000到0xc03FFFFF虚拟内存空间里,其中将页目录映射进0xc0300000,这恰恰是页表数组的768项,而这个页目录的768项设置的物理地址正好也是cr3的值,这样映射到0xc0300000的页目录同时也是页表,这就是自映射,这归功于它的页表连续的映射到了一个固定的位置,在windows中访问页表可以直接访问0xc0000000到0xc03FFFFF的虚存空间,而这在linux 却必须要从mm_struct到页表的转化了。
windows的pgd在EPROCESS结构的KPROCESS里面,但是linux的相应结构却在mm_struct里面,说明,在linux里面,遵循的理念就是地址空间和页目录的关系比进程和页目录的关系更加紧密。
最后说一下页面置换算法,在linux里面,内核维护了一个active链表和一个inactive链表,清页进程时常被唤起,然后扫描这两个链表,最后 释放能释放的内存,最好的办法还是看内核代码,或者,等着我以后分析代码。但是在windows里,链表却不只两个了,而是四个,连个仍然和进程关联的链 表,两个没有关联的,其中有关联的之一就是后备链表,这个只是将对应页表的有效位清除,但是却还是可以用的,如果一段时间没有用,就会彻底切断与进程的关联,放入空闲链表,最后将放入清零链表,这个就不多说了。在vista中,后备链表不只一个了,而是7个,按照优先级排列,如果非要清除一个后备链表的 页面时,将选择优先级最小的那个.
  windows的内存管理非常复杂,写得也非常不错,我特别看重的就是内存回收这一块。
最后简要谈一下我对linux做法和windows做法的理解,linux尽量拷贝现成的东西,默认大家区别不是很大,windows里面就不一样了,它遵循的是尽量一致,比如虚拟内存空间,windows中每一块虚拟内存干什么用基本说得都是清清楚楚,尽量把一切王确定的虚拟地址靠,但是linux中却 只规定一段物理映射区,一段高端映射区...至于说你怎么去用这些区域,那就不管了,所以任何数据结构在linux中都很难有固定的虚拟地址,在 windows中却有,这就是为什么黑客总是可以找到windows关键数据结构从而操作它们的原因之一吧。呵呵,linux真是虚无缥缈,招无定法,惊!


原文链接:http://blog.csdn.net/dog250/article/details/5302752
加载中
返回顶部
顶部