本文共 1996 字,大约阅读时间需要 6 分钟。
struct page *alloc_pages(gfp_t gfp, unsigned order)用于以gfp_mask方式分配2的order次方个连续物理页其使用的例程如下:static void *alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, gfp_t flag, unsigned long attrs){ struct page *page; page = alloc_pages(flag | __GFP_NOWARN, get_order(size)); if (!page) { if (!gfpflags_allow_blocking(flag)) return NULL; page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, get_order(size), flag); if (!page) return NULL; }}其源码分析如下:static inline struct page *alloc_pages(gfp_t gfp_mask, unsigned int order){ #直接调用内部函数alloc_pages_current,其形参和alloc_pages 一样 return alloc_pages_current(gfp_mask, order);}static struct mempolicy default_policy = { .refcnt = ATOMIC_INIT(1), /* never free it */ .mode = MPOL_PREFERRED, .flags = MPOL_F_LOCAL,};struct page *alloc_pages_current(gfp_t gfp, unsigned order){ #默认设置一个mempolicy,如果没有在中断环境中,后面会更换一个memppolicy struct mempolicy *pol = &default_policy; struct page *page; #从这里可以知道alloc_pages 可以用于中断环境中 if (!in_interrupt() && !(gfp & __GFP_THISNODE)) pol = get_task_policy(current); /* * No reference counting needed for current->mempolicy * nor system default_policy */ #从这里可以知道不是在中断环境中。 if (pol->mode == MPOL_INTERLEAVE) page = alloc_page_interleave(gfp, order, interleave_nodes(pol)); else page = __alloc_pages_nodemask(gfp, order, policy_node(gfp, pol, numa_node_id()), policy_nodemask(gfp, pol)); return page;}static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, unsigned nid){ struct page *page; #继续调用__alloc_pages 从numa 节点nid中申请order次方的page page = __alloc_pages(gfp, order, nid); /* skip NUMA_INTERLEAVE_HIT counter update if numa stats is disabled */ #这个if条件会在大概率下成立,因此一般这里就返回了 if (!static_branch_likely(&vm_numa_stat_key)) return page; #如果申请memory的numa id等于形参指定的nid if (page && page_to_nid(page) == nid) { preempt_disable(); #在禁止抢占的环境下增减numa state NUMA_INTERLEAVE_HIT 的计数 __inc_numa_state(page_zone(page), NUMA_INTERLEAVE_HIT); preempt_enable(); } return page;}
转载地址:http://rgjmi.baihongyu.com/