申请pages的基础知识在“Buddy system基础 ”这篇文章中已经讲过了,这里主要分析申请pages的代码。
代码框架
alloc_pages //alloc_pages_node(numa_node_id(), gfp_mask, order)
|----->return __alloc_pages_node(nid, gfp_mask, order);
| |----->return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask));
| | |----->return __alloc_pages_nodemask(gfp_mask, order, zonelist, NULL);
| | | |----->.high_zoneidx = gfp_zone(gfp_mask),
| | | | 根据传递进来的gfp_mask,选择从那个zone开始分配
| | | |----->.zonelist = zonelist,
| | | | 设置要从哪个zonelist分配,对于UMA来说,只有一个zonelist
| | | |----->.nodemask = nodemask,
| | | |----->.migratetype = gfpflags_to_migratetype(gfp_mask),
| | | | 根据传递进来的gfp_mask,选择要分配哪种迁移类型的page
| | | |----->ac.preferred_zoneref = first_zones_zonelist(ac.zonelist,
| | | | ac.high_zoneidx, ac.nodemask);
| | | | 找到最先使用的zone
| | | |----->page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
| | | | 遍历所有符合条件的zone,分配pages
| | | | |----->page = buffered_rmqueue(ac->preferred_zoneref->zone, zone, order,
| | | | | gfp_mask, alloc_flags, ac->migratetype);
| | | | | |----->如果order为0,即分配一个page,则走如下逻辑
| | | | | |----->pcp = &this_cpu_ptr(zone->pageset)->pcp;
| | | | | |----->list = &pcp->lists[migratetype];
| | | | | | 获取当前cpu的pageset链表,为该cpu分配的free pages会加入该链表
| | | | | |----->pcp->count += rmqueue_bulk(zone, 0, pcp->batch, list, migratetype, cold);
| | | | | | |----->struct page *page = __rmqueue(zone, order, migratetype);
| | | | | | | 从所选的zone,迁移类型为migratetype的free_list中,分配1个pages
|