Chinaunix首页 | 论坛 | 博客
  • 博客访问: 247997
  • 博文数量: 34
  • 博客积分: 938
  • 博客等级: 准尉
  • 技术积分: 440
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-18 12:07
文章分类

全部博文(34)

文章存档

2012年(28)

2011年(6)

分类: LINUX

2012-02-22 21:52:07

申请页面的函数调用:
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) |
0

上一篇:父亲

下一篇:六个内核中的页框分配API

给主人留下些什么吧!~~