static void __init free_area_init_core(struct pglist_data *pgdat,
unsigned long *zones_size, unsigned long *zholes_size)
{
unsigned long i, j;
int cpu, nid = pgdat->node_id;
unsigned long zone_start_pfn = pgdat->node_start_pfn; //该节点物理起始地址对应页帧号
pgdat->nr_zones = 0;
init_waitqueue_head(&pgdat->kswapd_wait);
pgdat->kswapd_max_order = 0;
for (j = 0; j < MAX_NR_ZONES; j++) {
struct zone *zone = pgdat->node_zones + j;
unsigned long size, realsize;
unsigned long batch;
realsize = size = zones_size[j];
if (zholes_size)
realsize -= zholes_size[j];
if (j == ZONE_DMA || j == ZONE_NORMAL)
nr_kernel_pages += realsize;
nr_all_pages += realsize;
zone->spanned_pages = size; //该内存页区总页数,包括孔洞页数
zone->present_pages = realsize; //该内存页区实际存在页数即页区总页数减去孔洞页数
zone->name = zone_names[j]; //该内存页区名字
spin_lock_init(&zone->lock);
spin_lock_init(&zone->lru_lock);
zone->zone_pgdat = pgdat;
zone->free_pages = 0; //该内存页区中的空闲页数
zone->temp_priority = zone->prev_priority = DEF_PRIORITY;
//临时优先级和预置优先级
batch = zone_batchsize(zone);
for (cpu = 0; cpu < NR_CPUS; cpu++) {
#ifdef CONFIG_NUMA
/* Early boot. Slab allocator not functional yet */
zone->pageset[cpu] = &boot_pageset[cpu];
setup_pageset(&boot_pageset[cpu],0);
#else
setup_pageset(zone_pcp(zone,cpu), batch);
#endif
}
printk(KERN_DEBUG " %s zone: %lu pages, LIFO batch:%lu/n",
zone_names[j], realsize, batch);
INIT_LIST_HEAD(&zone->active_list);
INIT_LIST_HEAD(&zone->inactive_list);
zone->nr_scan_active = 0; //扫描激活内存页数
zone->nr_scan_inactive = 0; //扫描未激活内存页数
zone->nr_active = 0; //激活内存页数
zone->nr_inactive = 0; //未激活内存页数
atomic_set(&zone->reclaim_in_progress, 0);
if (!size)
continue;
/*
* The per-page waitqueue mechanism uses hashed waitqueues
* per zone.
*/
zone->wait_table_size = wait_table_size(size); //该页区的等待队列链表结构指针
zone->wait_table_bits =
wait_table_bits(zone->wait_table_size);
zone->wait_table = (wait_queue_head_t *)
alloc_bootmem_node(pgdat, zone->wait_table_size
* sizeof(wait_queue_head_t));
for(i = 0; i < zone->wait_table_size; ++i)
init_waitqueue_head(zone->wait_table + i);
pgdat->nr_zones = j+1;
zone->zone_mem_map = pfn_to_page(zone_start_pfn);
//指向该内存页区包含的所有内存页的描述结构变量起始地址
zone->zone_start_pfn = zone_start_pfn;
//该内存页区的物理开始地址对应的页号
memmap_init(size, nid, j, zone_start_pfn);
zonetable_add(zone, nid, j, zone_start_pfn, size);
zone_start_pfn += size;
zone_init_free_lists(pgdat, zone, zone->spanned_pages);
}
}
memmap_init -->memmap_init_zone
void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone,
unsigned long start_pfn)
{
struct page *page;
unsigned long end_pfn = start_pfn + size;
unsigned long pfn;
for (pfn = start_pfn; pfn < end_pfn; pfn++, page++) {
if (!early_pfn_valid(pfn))
continue;
if (!early_pfn_in_nid(pfn, nid))
continue;
page = pfn_to_page(pfn); //页号对应的page页描述结构
set_page_links(page, zone, nid, pfn); //设置页标志字
set_page_count(page, 0); //设置页引用计数
reset_page_mapcount(page); //设置页映射计数器
SetPageReserved(page); //设置页保留位
INIT_LIST_HEAD(&page->lru);
#ifdef WANT_PAGE_VIRTUAL
/* The shift won't overflow because ZONE_NORMAL is below 4G. */
if (!is_highmem_idx(zone))
set_page_address(page, __va(pfn << PAGE_SHIFT));
#endif
}
}
void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
unsigned long size)
{
int order;
for (order = 0; order < MAX_ORDER ; order++) {
INIT_LIST_HEAD(&zone->free_area[order].free_list);
zone->free_area[order].nr_free = 0; //设置对应连续2^n页空闲内存区描述结构的数组,此处均设置为0
}
}