linux伙伴系统(一):基本结构

3.5 物理内存的管理--伙伴系统

    在内核初始化完成以后,内存管理的责任交给伙伴系统承担。伙伴系统基于一种相对简单而令人吃惊的强大算法,已经出现40年。它结合了优秀内存分配器的两个关键特征:速度和效率。

 

3.5.1 伙伴系统的数据结构

系统内存中的每个物理内存页(页帧),都对应一个struct page实例。每个内存域都关联了一个struct zone的实例,其中保存了用于管理伙伴数据的主要数组。

 

struct zone {

...

        /* free areas of different sizes */

        struct free_area        free_area[MAX_ORDER];

    ...

} ____cacheline_internodealigned_in_smp;

 

free_area是一个辅助数据结构,其定义如下:

struct free_area {

        struct list_head        free_list[MIGRATE_TYPES];

        unsigned long           nr_free;

};

nr_free指定了当前内存区中空闲页块的数目(对0阶内存区主页计算,对1阶内存计算页对的数目,对2阶内存区计算4页集合的数目,依次类推)。

free_list是用于连接空闲页的链表。页链表包含大小相同的连续内存区。

阶是伙伴系统中的重要术语,它描述了内存分配的数量单位。内存块的长度是2^order,其中order的范围从0MAX_ORDER.

/* Free memory management - zoned buddy allocator.  */

#ifndef CONFIG_FORCE_MAX_ZONEORDER

#define MAX_ORDER 11

#else

#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER

#endif

#define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))

该常数通常设置为11,这意味着一次分配可以请求的页数最大是2^11=2048 pages2K*4K=8MBytes)。如果特定于体系结构的代码设置了FORCE_MAX_ZONEORDER配置选项,该值也可以手工改变。例如,IA-64系统上巨大的地址空间可以处理MAX_ORDER=18的情形,而ARMv850系统则使用更小的值,如89,但这不一定是由计算机支持的内存数量比较小引起的,也可能是内存对齐方式的要求所导致。

free_area[]数组中各个元素的索引页解释为阶,用于指定对应链表中的连续内存区包含多少个页帧。第0个链表包含的内存区为单页(2^0=1),第一个链表管理的内存区为两页(2^1=2),第3个管理的内存区为4页,依次类推。

内存区是如何连接的?内存区中第1页的链表元素,可用于将内存区维持在链表中。因此,也不必引入新的数据来管理物理内存上的连续的页,否则这些页不可能在同一内存区中。图3-22给出了图示。

伙伴不必是连接的。如果一个内存区在分配期间分解为两半,内核会自动将未用的一半加入到对应的链表中。如果在未来的某个时刻,由于内存释放的缘故,两个内存区都处于空闲状态,可通过判断其是否为伙伴。管理工作较少,是伙伴系统的一个优点。

基于伙伴系统的内存管理专注于某个结点的某个内存域,例如,DMA或高端内存域。但所有内存域和结点的伙伴系统都通过备用分配列表连接起来,如图3-23所示。

linux伙伴系统(一):基本结构_第1张图片

在首选的内存域结点无法满足内存分配请求时,首先尝试同一节点的另一个内存域,接下来尝试另一个结点,直至满足请求。

最后要注意,有关伙伴系统当前状态的信息可以通过/proc/buddyinfo获取,也可以通过echo m >/proc/sysrq-trigger获取:

 

root@linux:/study/linux-git/linux-3.18.3# echo m >/proc/sysrq-trigger 

[32594.375485] SysRq : Show Memory

..........

[32594.625700] DMA: 2*4kB (U) 1*8kB (E) 1*16kB (M) 2*32kB (EM) 2*64kB (EM) 1*128kB (E) 3*256kB (UEM) 3*512kB (EM) 1*1024kB (U) 1*2048kB (R) 0*4096kB = 5728kB

[32594.640749] Normal: 36*4kB (UEM) 11*8kB (UM) 12*16kB (UEM) 4*32kB (UEM) 0*64kB 2*128kB (EM) 7*256kB (UEM) 4*512kB (UM) 3*1024kB (UM) 8*2048kB (UER) 26*4096kB (UMR) = 130600kB

[32594.657634] HighMem: 2*4kB (UM) 18*8kB (UE) 53*16kB (UM) 57*32kB (UEM) 32*64kB (UEM) 15*128kB (UE) 9*256kB (UE) 8*512kB (UE) 7*1024kB (UE) 7*2048kB (UEM) 65*4096kB (UMR) = 300936kB

root@linux:/study/linux-git/linux-3.18.3# 

root@linux:/study/linux-git/linux-3.18.3# cat /proc/buddyinfo 

Node 0, zone      DMA      2      1      1      2      2      1      3      3      1      1      0 

Node 0, zone   Normal     36     10     12      4      0      2      7      4      3      8     26 

Node 0, zone  HighMem     13     28     53     57     32     15      9      8      7      7     65 

root@linux:/study/linux-git/linux-3.18.3# 

你可能感兴趣的:(linux伙伴系统(一):基本结构)