文章目录
alloc_pages源码流程分析
alloc_pages开始了真正的页面申请,函数作用是:用于申请一块2^order的连续物理内存块
alloc_pages函数实现流程

代码细节分析
参数准备
//include/linux/gfp.h
/*numa_node_id()返回当前所在节点编号*/
#define alloc_pages(gfp_mask, order) \
alloc_pages_node(numa_node_id(), gfp_mask, order)
static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
unsigned int order)
{
//nid最好是传递过来的参数,若参数无效,则会选择一个目前距离cup最近的一个在线节点
if (nid == NUMA_NO_NODE)
nid = numa_mem_id();
return __alloc_pages_node(nid, gfp_mask, order);
}
static inline struct page *
__alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order)
{
VM_BUG_ON(nid < 0 || nid >= MAX_NUMNODES);
VM_WARN_ON(!node_online(nid));
//node_zonelist(nid, gfp_mask)是用于获取node节点的zone管理区列表,按优先级顺序存储
return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask));
}
static inline struct page *
__alloc_pages(gfp_t gfp_mask, unsigned int order,
struct zonelist *zonelist)
{
return __alloc_pages_nodemask(gfp_mask, order, zonelist, NULL);
}
核心函数__alloc_pages_nodemask
_alloc_pages_nodemask是伙伴系统的心脏,处理实质的内存分配工作。
- (1)先进行参数初始化:alloc_mask, alloc_flags和struct alloc_context ac,用于决定内存块的分配配条件。
- (2) get_page_from_freelist:内核内存环境良好,直接进行快速分配,若成功返回获取free内存块
- (3)__alloc_pages_slowpath:当前内存环境恶劣时,进入慢分配流程,若成功返回free内存块
- (4)获取空间内存块后对内存块和系统环境做检查,满足预定要求则返回申请的内存给内核使用
//mm/page_alloc.c
struct page *
__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
struct zonelist *zonelist, nodemask_t *nodemask)
{
struct page *page;
//分配标志,仅在低水位water mark及以上限制页面分配
unsigned int alloc_flags = ALLOC_WMARK_LOW;
gfp_t alloc_mask = gfp_mask; /* The gfp_t that was actually used for allocation */
//用于存储函数间传递的参数
struct alloc_context ac = {
//gfp对应的zone,参考文档'如何根据gfp_flag找到对应的zone',内存分配的zoneidx一定小于等于该idx
.high_zoneidx = gfp_zone(gfp_mask),
//zone优先级搜索列表
.zonelist = zonelist,
.nodemask = nodemask,
//根据gfp找到迁移类型,gfp_flags的bit3-bit4表示migrate类型
.migratetype = gfpflags_to_migratetype(gfp_mask),
};
if (cpusets_enabled()) {
alloc_mask |= __GFP_HARDWALL;
alloc_flags |= ALLOC_CPUSET;
if (!ac.nodemask)
ac.nodemask = &cpuset_current_mems_allowed;
}
gfp_mask &= gfp_allowed_mask;
//需要CONFIG_TRACE_IRQFLAGS和CONFIG_PROVE_LOCKING同时定义的时候,才起作用,否则为空函数
lockdep_trace_alloc(gfp_mask);
/*如果申请页面传入的gfp_mask掩码携带__GFP_WAIT标识,表示允许页面申请时休眠,
*则会进入might_sleep_if()检查是否需要休眠等待以及重新调度
*/
might_sleep_if(gfp_mask & __GFP_DIRECT_RECLAIM);
//由于未设置CONFIG_FAIL_PAGE_ALLOC,则should_fail_alloc_page()恒定返回false
if (should_fail_alloc_page(gfp_mask, order)

最低0.47元/天 解锁文章
688

被折叠的 条评论
为什么被折叠?



