注:原创作品,转载请注明。
1. Linux 内核对各个zone都有一个buddy system.
2. 数据结构:
mem_map:一个Struct page数组,对应系统中所有的物理内存页。
而每一个zone结构里都有一个zone_mem_map域指向这个zone的第一个page 在mem_map的位置,还有一个域size代表这个区的大小,即总共有多少页。
每一个zone都有自己的buddy system,由下面的zone结构就可以看出。
空闲块是根据其大小做的保存,特别强调的是struct free_area free_area[MAX_ORDER];
保存着zone中的空闲块。数组中的每一个元素都有个双链表结构。比如说 free_area中第K个元素保存着大小为2的k次方大小的块的链表结构。数组中保存的是表头结构,即指向第一个2的k次方大小块的第一个页面。那块的剩余的页面怎么办?不用管,因为都是按块来操作的,只需要知道块的第一个页面即可,最后一个页面就是第一个页面加上2的k次方。同属于一个链表的块与块之间由每一个块的第一个页面的struct page 中的list_head lru来相互链接。
#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))
struct free_area {
struct list_head free_list;
unsigned long nr_free;
};
struct zone {
/* Fields commonly accessed by the page allocator */
unsigned long free_pages;
unsigned long pages_min, pages_low, pages_high;
/*
* We don't know if the memory that we're going to allocate will be freeable
* or/and it will be released eventually, so to avoid totally wasting several
* GB of ram we must reserve some of the lower zone memory (otherwise we risk
* to run OOM on the lower zones despite there's tons of freeable ram
* on the higher zones). This array is recalculated at runtime if the
* sysctl_lowmem_reserve_ratio sysctl changes.
*/
unsigned long lowmem_reserve[MAX_NR_ZONES];
#ifdef CONFIG_NUMA
struct per_cpu_pageset *pageset[NR_CPUS];