alloc_pages函数实现:
#define alloc_pages(gfp_mask, order) \
alloc_pages_node(numa_node_id(), gfp_mask, order)
上图的nid是针对numa,此处不做引入分析,可以直接将nid当做0分析。
__alloc_pages函数是透传调用__alloc_pages_nodemask(gfp_mask, order, zonelist, NULL);
gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK;
__GFP_BITS_MASK包含所有的存在含义的标志位。
#define GFP_BOOT_MASK (__GFP_BITS_MASK & ~(__GFP_WAIT|__GFP_IO|__GFP_FS))
上述代码的2809-2813行是定义一个局部变量alloc_context变量,并且初始化了优先分配的zone索引high_zonidx,nodemask=NULL,根据gfp标志算出分配的迁移类型。上述2815行是计算出合法的gfp_mask。2821行相当于是进行参数合法性检查2829-2830是进行zone的参数合法性检查。2832-2833是针对开启了CMA则指定ALLOC_CMA分配标志,其中2839-2843是决定从哪个zone分配内存,first_zones_zonelist函数会根据传入的gfp找到对应的目标zone,然后再全局的zonelist链表里搜索到索引值小于等于目标zone对应的索引值的zone。
在分析first_zones_zonelist函数之前先分析下数据结构。2850行get_page_from_freelist是真正执行分配任务的函数,详细实现参考1.2节。2851-2860是针对分配失败的情况这个后面会继续分析。2874-2875会再一次尝试。2877则是返回分配成功的page结构地址。
内存分配标志
下面标志表示对应的区域分配
#define __GFP_DMA ((__force gfp_t)___GFP_DMA) DMA zone分配
#define __GFP_HIGHMEM ((__force gfp_t)___GFP_HIGHMEM)
#define __GFP_DMA32 ((__force gfp_t)___GFP_DMA32)
#define __GFP_MOVABLE ((__force gfp_t)___GFP_MOVABLE) /* Page is movable */
#define GFP_ZONEMASK (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
下面分配标志改变分配的行为,每个分配标志代码里都有详细的注释
#define __GFP_WAIT ((__force gfp_t)___GFP_WAIT) /* Can wait and reschedule? */
#define __GFP_HIGH ((__force gfp_t)___GFP_HIGH) /* Should access emergency pools? */
#define __GFP_IO ((__force gfp_t)___GFP_IO) /* Can start physical IO? */
#define __GFP_FS ((__force gfp_t)___GFP_FS) /* Can call down to low-level FS? */
#define __GFP_COLD ((__force gfp_t)___GFP_COLD) /* Cache-cold page required */
#define __GFP_NOWARN ((__force gfp_t)___GFP_NOWARN) /* Suppress page allocation failure warning */
#define __GFP_REPEAT ((__force gfp_t)___GFP_REPEAT) /* See above */
#define __GFP_NOFAIL ((__force gfp_t)___GFP_NOFAIL) /* See above */
#define __GFP_NORETRY ((__forc