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
真是虚无缥缈,招无定法,
惊!