申请页面的函数调用:
alloc_pages->
->alloc_pages_node
->__alloc_pages
->__alloc_pages_nodemask
->get_page_from_freelist
->__alloc_pages_slowpath
->wake_all_kswapdb 调用wake_all_kswapd()唤醒每个zone所属node中的kswapd守护进
->gfp_to_alloc_flags
-> get_page_from_freelist
->__alloc_pages_high_priority
->get_page_from_freelist
->__alloc_pages_direct_compact
->__alloc_pages_direct_reclaim
->try_to_free_pages
->get_page_from_freelist
->__alloc_pages_may_oom
以缩进及->表示调用层次。
__alloc_pages_nodemask是buddy的核心。get_page_from_freelist可以看作是buddy allocator的前置函数。
它通过分配标志和分配阶判断是否能进行此次内存分配。如果可以分配,则它进行实际的内存分配工作,既利用伙伴算法进行分配内存。
否则,进入__alloc_pages_slowpath(),此时内核需要放宽一些分配条件,然后在__alloc_pages_slowpath()中再调用几次get_page_from_freelist()。
这种情况在内存分配过程中很常见,大多数情况下第一次调用get_page_from_freelist()都会失败。
allog_pages定义在src/include/gfp.h中:
#ifdef CONFIG_NUMA
extern struct page *alloc_pages_current(gfp_t gfp_mask, unsigned order);
static inline struct page *
alloc_pages(gfp_t gfp_mask, unsigned int order)
{
return alloc_pages_current(gfp_mask, order);
}
extern struct page *alloc_page_vma(gfp_t gfp_mask,
struct vm_area_struct *vma, unsigned long addr);
#else
#define alloc_pages(gfp_mask, order) \
alloc_pages_node(numa_node_id(), gfp_mask, order)
#define alloc_page_vma(gfp_mask, vma, addr) alloc_pages(gfp_mask, 0)
#endif
我们只分析UMA的情况。
alloc_pages_node(numa_node_id(), gfp_mask, order),其中numa_node_id()定义在
src/include/gfp.h中:
#ifndef numa_node_id
/* Returns the number of the current Node. */
static inline int numa_node_id(void)
{
return __this_cpu_read(numa_node);
}
#endif
返回当前CPU的编号,只有一个CPU,所以返回0。
alloc_pages_node在src/include/gfp.h实现:
static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
unsigned int order)
{
/* Unknown node is current node */
if (nid < 0)
nid = numa_node_id();
//printk(KERN_NOTICE "alloc_pages_node nid: %d, gfp_mask: 0x%08x\n", nid, (unsigned)gfp_mask);
return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask));
}
第三个参数根据nif和gfp_mask得到zonelist。在UMA中,node的zonelist为1,在NUMA中,为2。
alloc_pages_node会调用__alloc_pages,而__alloc_pages就在alloc_pages_node的上面,在LINUX内核中,经常有下面的函数调用上面
刚定义函数的情况。
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了,其实现在src/mm/page_alloc.c中,正如它开头的注释所说
/*
* This is the 'heart' of the zoned buddy allocator.
*/
这个函数是伙伴系统的核心。
阅读(3670) | 评论(0) | 转发(0) |