页面分配和释放函数
页面核心分配函数:
struct page * alloc_pages(gfp_t gfp_mask, unsigned int order)
alloc_page(gfp_mask)
unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
释放函数:
void free_pages(unsigned long addr, unsigned int order);
__free_page(page)
free_page(addr)
alloc_pages
static inline struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
struct page *alloc_pages_current(gfp_t gfp, unsigned order)
struct page *__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid,nodemask_t *nodemask)
page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
page = __alloc_pages_slowpath(alloc_mask, order, &ac);
get_page_from_freelist 尝试分配物理页面,如果分配失败了.使用__alloc_pages_slowpath,进入慢速分配路径
get_page_from_freelist
for_next_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,ac->nodemask)
找到从那些zone中分配内存
//当找到从zone分配内存后,需要进行一些必要的检查
if (cpusets_enabled() &&
(alloc_flags & ALLOC_CPUSET) &&
! (zone, gfp_mask))
continue;
//检测当前的zone的watemark水位是否充足WMARK_LOW水位
if (zone_watermark_ok(zone, order, mark,
ac_classzone_idx(ac), alloc_flags))
free_pages
void free_pages(unsigned long addr, unsigned int order)
__free_pages(virt_to_page((void *)addr), order);
free_the_page(page, order);
__free_pages_ok(page, order);
free_one_page(page_zone(page), page, pfn, order, migratetype);
migratetype = get_pfnblock_migratetype(page, pfn);
list_add(&page->lru, &zone->free_area[order].free_list[migratetype]);
释放内存页面的核心功能是把页面添加到伙伴系统中适当的free_area链表.在释放内存块的时候,会查询相邻内存块是否空闲,如果也是空闲的就会将当前块继续加到更加高一阶的空闲链表free_area中(页面合并),一直到可能合并的内存块都完成合并.