本文共 2853 字,大约阅读时间需要 9 分钟。
Discontiguous memory support,即非连续内存管理
主要数据结构 struct bootmem_data
#ifndef CONFIG_NO_BOOTMEM/* * node_bootmem_map is a map pointer - the bits represent all physical * memory pages (including holes) on the node. */typedef struct bootmem_data { unsigned long node_min_pfn; unsigned long node_low_pfn; void *node_bootmem_map; unsigned long last_end_off; unsigned long hint_idx; struct list_head list;} bootmem_data_t;extern bootmem_data_t bootmem_node_data[];#endif
相关数据对象定义:
#ifndef CONFIG_NEED_MULTIPLE_NODESstruct pglist_data __refdata contig_page_data = { .bdata = &bootmem_node_data[0]};EXPORT_SYMBOL(contig_page_data);#endifunsigned long max_low_pfn;unsigned long min_low_pfn;unsigned long max_pfn;unsigned long long max_possible_pfn;bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata;static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list);static int bootmem_debug;
bootmem 对外提供了两个初始化函数,即init_bootmem()和init_bootmem_node(),很容易理解这两个函数不同,
/** * init_bootmem_node - register a node as boot memory * @pgdat: node to register * @freepfn: pfn where the bitmap for this node is to be placed * @startpfn: first pfn on the node * @endpfn: first pfn after the node * * Returns the number of bytes needed to hold the bitmap for this node. */unsigned long __init init_bootmem_node(pg_data_t *pgdat,
unsigned long freepfn, unsigned long startpfn,
unsigned long endpfn){ return init_bootmem_core(pgdat->bdata, freepfn, startpfn, endpfn);}/** * init_bootmem - register boot memory * @start: pfn where the bitmap is to be placed * @pages: number of available physical pages * * Returns the number of bytes needed to hold the bitmap. */unsigned long __init init_bootmem(unsigned long start,
unsigned long pages){ max_low_pfn = pages; min_low_pfn = start; return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages);}
/* * Called once to set up the allocator itself. */static unsigned long __init init_bootmem_core(bootmem_data_t *bdata, unsigned long mapstart, unsigned long start, unsigned long end){ unsigned long mapsize; mminit_validate_memmodel_limits(&start, &end); bdata->node_bootmem_map = phys_to_virt(PFN_PHYS(mapstart)); bdata->node_min_pfn = start; bdata->node_low_pfn = end; link_bootmem(bdata); /* * Initially all pages are reserved - setup_arch() has to * register free RAM areas explicitly. */ mapsize = bootmap_bytes(end - start); memset(bdata->node_bootmem_map, 0xff, mapsize); bdebug("nid=%td start=%lx map=%lx end=%lx mapsize=%lx\n", bdata - bootmem_node_data, start, mapstart, end, mapsize); return mapsize;}
/* * link bdata in order */static void __init link_bootmem(bootmem_data_t *bdata){ bootmem_data_t *ent; list_for_each_entry(ent, &bdata_list, list) { if (bdata->node_min_pfn < ent->node_min_pfn) { list_add_tail(&bdata->list, &ent->list); return; } } list_add_tail(&bdata->list, &bdata_list);}
转载地址:http://rmqti.baihongyu.com/