该函数设置:
1.pgdata节点的成员
2.pgdata->zone的成员
3.初始化zone->free_area
4.初始化zone所包含的所有页对应的页框描述符page结构体
/* 为buddy系统设置为无可用的页。 初始化zone->free_area,设置为buddy系统中没有可用的页框。 */ static void __init bootmem_free_node(int node, struct meminfo *mi) -->1.计算各个zone中的有效页框数及全部页框数(含空洞) -->free_area_init_node(node, zone_size, start_pfn, zhole_size); -->设置pglist_data结构体的成员(pgdat->node_start_pfn,node_spaned_pages,node_present_pages) /* 为节点中的每一个页分配一个页框描述符page结构体,这些结构体所占用的内存 调用bootmem分配器的API分配,alloc_bootmem_node */ -->alloc_node_mem_map(pgdat); -->free_area_init_core(pgdat, zones_size, zholes_size); -->unsigned long __meminitdata nr_kernel_pages;//内核可用的所有页框数 -->unsigned long __meminitdata nr_all_pages;//所有页框数 -->设置zone结构体的成员 -->zone_pcp_init(zone);//初始化每CPU的冷热页缓存 //把多个页框组织为一个pageblock,每个pageblock用几bit标记,为所有标记分配内存 -->setup_usemap(pgdat, zone, size); -->init_currently_empty_zone(zone, zone_start_pfn,size, MEMMAP_EARLY); -->设置pglist_data->nr_zone -->zone_init_free_lists(zone);//初始化zone->free_area。设置为无空闲页可用 -->memmap_init(size, nid, j, zone_start_pfn); -->memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY) -->unsigned long highest_memmap_pfn//最大的页框号,线性映射区 -->struct page *page = pfn_to_page(pfn); -->set_page_links(page, zone, nid, pfn);//设置page->flags -->init_page_count(page);//page->_ncount=1 -->reset_page_mapcount(page); //page->_mapcount=-1 -->SetPageReserved(page); //设置page->flags PG_reserved位
注意上面的SetPageReserved(page)在代码中搜索不到该函数,在include/linux/page_flags.h中有下列宏用于定义page->flags相关的操作函数。
/* * Macros to create function definitions for page flags */ #define TESTPAGEFLAG(uname, lname) \ static inline int Page##uname(struct page *page) \ { return test_bit(PG_##lname, &page->flags); } #define SETPAGEFLAG(uname, lname) \ static inline void SetPage##uname(struct page *page) \ { set_bit(PG_##lname, &page->flags); } #define CLEARPAGEFLAG(uname, lname) \ static inline void ClearPage##uname(struct page *page) \ { clear_bit(PG_##lname, &page->flags); }