linux 物理页面分配
核心接口函数
alloc_pages:
include/linux/gfp.h
static inline struct page *
alloc_pages(gfp_t gfp_mask, unsigned int order)
用来分配2的order次幂个连续的物理页面,返回第一个物理页面的page数据结构.
mm/page_alloc.c
if (unlikely(order >= MAX_ORDER)) {
WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN));
return NULL;
}
MAX_ORDER
需要小于MAX_ORDER,默认是11
include/linux/mmzone.h
#ifndef CONFIG_FORCE_MAX_ZONEORDER
#define MAX_ORDER 11
#else
#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
#endif
__get_free_pages:
unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order){
struct page *page;
page = alloc_pages(gfp_mask & ~__GFP_HIGHMEM, order);
if (!page)
return 0;
return (unsigned long) page_address(page);
}
返回分配内存空间的虚地址,从gfp_mask & ~__GFP_HIGHMEM
这个函数不会使用内核的高端地址.
分配一个物理页
#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
#define __get_free_page(gfp_mask) \
__get_free_pages((gfp_mask), 0)
只是将order值设置为0,注意使用alloc_page
正常来说是会填充一些不确定的值.但是内核提供了一个可以返回全0页面的接口
include/linux/gfp.h
extern unsigned long get_zeroed_page(gfp_t gfp_mask);
unsigned long get_zeroed_page(gfp_t gfp_mask)
{
return __get_free_pages(gfp_mask | __GFP_ZERO, 0);
}
给gfp_mask
(分配掩码)添加了一个 __GFP_ZERO
标志
页面的释放
#define free_page(addr) free_pages((addr), 0)
__free_pages(virt_to_page((void *)addr), order);
void __free_pages(struct page *page, unsigned int order)