Chinaunix首页 | 论坛 | 博客
  • 博客访问: 581474
  • 博文数量: 213
  • 博客积分: 6789
  • 博客等级: 准将
  • 技术积分: 1947
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-01 17:11
文章分类

全部博文(213)

文章存档

2012年(9)

2011年(62)

2010年(99)

2009年(43)

分类: LINUX

2010-07-29 13:18:38

在内核初始化完成后,内存管理的责任由伙伴系统承担。
1 伙伴系统的结构
系统内存中的每个物理内存页(页桢),都对应于一个struct page。每个内存域关联一个struct zone,其中保存了用于管理伙伴数据的主要数组。
struct zone{
      ...
      struct free_area free_area[MAX_ORDER];
      ...
};
struct free_area{
    struct list_head free_list[MIGRATE_TYPES];
    unsigned long nr_free;
};
是伙伴系统中一个重要术语,它描述了内存分配的数量单位。内存块的长度为2的order(阶)次方。该常数通常设置为11,这意味着一次分配可以请求的页数最大是2的11次方(2048),IA-64或许大一些,ARM或许小一些。
free_area[]数组中各个元素的索引就解释为阶,用于指定对应链表中的连续内存区包含多少个页桢,简单的说,就是第0个链表代表第一阶,内存区为单页,第一个链表代表第一阶内存区为2的1次方为2页,以此类推。
每个内存区又是如何连接的呢?内存区的第一个页内的链表元素就干这件事,它将内存区维持在链表中
伙伴不必是彼此连接的。如果在一个内存区在分配期间,内核把一半占用了,另一半加到了链表中,如果在未来的模个时刻,由于内存释放的缘故,两个内存区都为空闲,可通过地址判断是不是伙伴。
如果内存分配请求超出内存域或者结点,那么要首先尝试另一个内存域,接下来是下一个结点。从小范围到大范围尝试,知道满足。
有关伙伴系统的信息可以通过下面方式获得
chechunli@chechunli-desktop:~ $ cat /proc/buddyinfo 
Node 0, zone      DMA     56     12      7      5      6      4      2      2      1      0      1 
Node 0, zone   Normal    693    306     67     34     12      9     11     20     20      1      0 
Node 0, zone  HighMem    519     94     13      3      2      0      2      0      1      0      0 
上述输出给出了各个内存域中每个分配阶中空闲项的数目,从左到右,阶依次升高。

2 释放页
__free_pages是一个基础函数,用于实现内核API中所有涉及内存释放的函数。
__free_pages
    |->是否为单页 --是-->free__hot_page
          |--否-->__free_pages_ok->__free_one_pages
释放时候,首先判断释放的内存是否为单页,要是单页的话,直接释放到per-CPU缓存中,对很可能出现在CPU高速缓存的页,则放置到热页列表中。如果per-CPU中的页数超过了自己所能容纳的数量,则释放一部分,还给伙伴系统,这个策略称为惰性合并,这样避免了单页返回给系统,系统合并,然后再拆分的麻烦。惰性合并阻止了大量白费的时间浪费。要是多于一页,则放回伙伴系统。

3 内核中不连续页的分配
我们知道连续的映射对内核是最好的,但并不总能成功的使用,在分配一大块内存时,可能竭尽全力也无法找到连续的内存块。在用户空间不存在这样的问题,因为普通进程设计为使用处理器的分页机制,当然这会降低速度并占用TLB。
内核中也可以这样实现,内核分配了虚拟地址空间的一部分,用于建立连续映射。在不连续的地址空间中就是这样实现的,vmalloc区就是虚拟地址空间。vmalloc是一个管理不连续内存的区域。
阅读(979) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~