内存区(memory area)是指具有连续的物理地址和任意长度的内存单元序列。
伙伴系统采用页框(一般取值4KB)作为基本内存区,适合于大内存的请求,但对小内存的请求容易造成内碎片。伙伴系统的调用是为了获得存放新内存区所需的额外页框,同时也为了释放不再包含内存区的页框,用一个动态链表来记录每个页框所包含的空闲内存区。
为了解决内碎片的问题,将内存区大小按几何分布划分,也就是将内存区划分成 2 的幂的大小。不论请求的大小多大,总能保证内碎片小于内存区的 50%。
Linux内核建立了13 个按几何分布的空闲内存区链表,大小从 32B~128KB。
物理内存被划分为 3 个区来管理,它们是 ZONE_DMA、 ZONE_NORMAL 和ZONE_HIGHMEM。每个区都用 struct zone_struct 结构表示, 定义于 include/linux/mmzone.h:
typedefstructzone_struct {
/* Commonly accessed fields:*/
spinlock_tlock;
unsignedlongfree_pages;
unsignedlongpages_min, pages_low, pages_high;
intneed_balance;
/* free areas of different sizes */
free_area_tfree_area[MAX_ORDER];
/* Discontig memory support fields.*/
structpglist_data*zone_pgdat;
structpage*zone_mem_map;
unsignedlongzone_start_paddr;
unsignedlongzone_start_mapnr;
/* rarely used fields: */
char*name;
unsignedlongsize;
} zone_t;lock :用来保证对该结构中其他域的串行访问。
free_pages :在这个区中现有空闲页的个数。
pages_min、 pages_low及 pages_high 是对这个区最少、次少及最多页面个数的描述。
need_balance:与 kswapd 合在一起使用。
free_area:在伙伴分配系统中的位图数组和页面链表。
zone_pgdat:该管理区所在的存储结点。
zone_mem_map:该管理区的内存映射表。
zone_start_paddr:该管理区的起始物理地址。
zone_start_mapnr:在 mem_map 中的索引(或下标)。
name:该管理区的名字。