内存管理综述(2.6.21)
R.wen
在物理内存页方面,linux从2.6.11开始使用4级页表来管理。分别是pgd, pud, pmd和pte,但是i386只是
使用了其中的两级--pgd和pte,因为1024×1024×4K = 4G,已经满足了i386的要求。
物理页面的分配方面,linux使用buddy算法。在支持NUMA的系统上,它首先将内存分成几个不同的节点
NODE,然后每个节点再分成不同的区域(ZONES),目前有三个区域--zone_dma(16M),zone_nomal(16
~896M),zone_highmem(896~1024M)。高端内存应该是历史的产物,再64位的系统上,它是不需要的
。
为了避免内存碎片,再分配小额内存的时候,Linux使用slab分配器。它的原理大概如下,首先它从buddy
系统中请求一定的物理页面(slab),然后再将它细分成objects, 这些object是物理上连续的,所以它又
通过一个数组来管理,并且通过使用一个slab管理的描述符,将这个数组串成链表。这是一个数组链表数
据结构的典型应用。kmalloc也是通过slab来实现的,一般情况下,它可分配的最大内存是128K.
在物理页面的分配上,上面两种算法有一个共同的特点,他们都使用了per-CPU cache.在buddy算法上,
如果使用者只是请求一个页面,它就从这个cache中分配,否则才从buddy系统中分配。而对于slab分配器
,它总是从当前CPU的cache中去分配的,如果这个cache为空,它就会从slab中取出相应的objs将这个
cache填满。这样就可以在SMP的情况下避免了锁的争用,大大的提高了SMP系统的并行性。
在进程地址空间方面,它是用mm_struct来描述一个进程的内存空间的。而用vm_area_struct结构来管理
地址区域的。在物理页面的分配上,linux使用lazy computing做法,即它是到产生缺页中断的时候才真
正去分配物理页面的。最终将这个页面物理地址写入相应的PTE。
还有一个值得注意的问题是有关高端内存的。
当系统的物理内存大于896M时,高于这个值的内存不能被直接映射,而是要在使用的时候建立。进程在内
核态的1G空间的映射关系如下:
gap KMAP_BASE
|===========|======|=========================|====|==========|=============|
mem_map VMLLOC_START VMLLOC_END gap FIXADDR_START FIXADDR_TOP
其中mem_map这一段是物理内存的大小,紧接着是一个大小为8M的gap,它是为了不要越界访问物理内存而
存在的。接下去就是用于管理高端内存的区域了。这个区域的最小值是VMALLOC_RESERVE,为128M,所以
在1G的内核地址空间中,只能用1G-128M=896M的地址建立直接映射。这个128M是个经验值,如果这个值太
大了,则能用于直接映射的物理内存的地址空间就小了,这样在使用内存的时候才建立映射,会影响系统
的性能。另一方面,如果这个值太小了,则同时能用的高端内存的量就更少了,会造成内存的浪费。所以
说这是一个考虑时间与空间的平衡值。
其中,FIXADDR_START到FIXADDR_TOP这段空间非常小,使用于建立临时映射的。它的接口是kmap_atomic
()。 内核只为每个CPU保留几个页面的地址空间。
接着是KMAP_BASE开始的一段,大小是LAST_PKMAP×PAGE_SIZE=1024×4K=4M。这段空间是用于kmap()建立
永久映射的。
剩下的一段就是VMLLOC_START与VMLLOC_END之间的空间了。它是由vmalloc分配的内存地址空间,因为由
它分配的物理内存是在分配时临时建立的,而且是逐页分配,不是一次性分配多个连续页的。所以,由它
分配的空间在线性地址上是连续的,但在物理上却可能是不连续的。注意这个区间上的空间是由
vm_struct描述的,而不是进程区域的vm_area_struct.不是同一个结构。
有一个外在的表现就是,由vmalloc(), kmap(), kmap_atomic()分配的内存得到的线性地址都是在
VMALLOC_START之上的。
posted on 2008-08-22 14:16
puppy 阅读(247)
评论(0) 编辑 收藏 引用