好奇struct page的存储,是在什么地方。
<mmzone.h>
typedef struct pglist_data {
struct zone node_zones[MAX_NR_ZONES];
struct zonelist node_zonelists[MAX_ZONELISTS];
int nr_zones;
struct page *node_mem_map;
struct bootmem_data *bdata;
unsigned long node_start_pfn;
unsigned long node_present_pages; /* 物理内存页的总数 */
unsigned long node_spanned_pages; /* 物理内存页的总长度,包含洞在内 */
int node_id;
struct pglist_data *pgdat_next;
wait_queue_head_t kswapd_wait;
struct task_struct *kswapd;
int kswapd_max_order;
} pg_data_t;
在UMA系统里面
static void __ref alloc_node_mem_map(struct pglist_data *pgdat)
mem_map = NODE_DATA(0)->node_mem_map;
mem_map是全局变量,是struct page 的全局数组, 其中的内容可以通过 pfn 也就是page frame number 来进行索引。
所以所有的page结构都是放在这个 数组里面,然后通过 pfn访问。而不是利用page头间错的使用。
而且这个地址可以从任意的ko进行访问到~~
alloc_node_mem_map 调用顺序如下:
Setup_arch
bootmem_init(); bootmem分配器 用于在启动阶段早期分配内存
zone_sizes_init(min, max); UMA和NUMA同名
free_area_init_nodes(max_zone_pfns); 架构无关 NUMA
free_area_init_node(0, zone_size, min, zhole_size);(架构无关UMA少个S!!)
alloc_node_mem_map
NODE_DATA node_data----------------NUMA
#define NODE_DATA(nid) (&contig_page_data)
struct pglist_data __refdata contig_page_data;
mem_map == (struct pglist_data *pgdat)NODE_DATA(0)->node_mem_map;
struct page *mem_map; !!
内核会将所有struct page* 放到一个全局数组(mem_map)中,而内核中我们常会看到pfn,说得就是页帧号,也就是数组的index,这里的MAX_ARCH_PFN就是系统的最大页帧号,但这个只是理论上的最大值,在start_kernel()时,setup_arch()函数会通过e820_end_of_ram_pfn()函数来获得实际物理内存并返回最终的max_pfn,可以看下e820_end_of_ram_pfn的实现(其内部直接调用e820_end_pfn函数)
来自 <https://www.cnblogs.com/emperor_zark/archive/2013/03/15/linux_page_1.html>
ZONE_MOVABLE