Chinaunix首页 | 论坛 | 博客
  • 博客访问: 379638
  • 博文数量: 87
  • 博客积分: 983
  • 博客等级: 准尉
  • 技术积分: 685
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-25 07:20
文章分类

全部博文(87)

文章存档

2016年(1)

2015年(3)

2014年(55)

2013年(13)

2012年(15)

分类: LINUX

2014-07-11 15:58:19

 

    本节介绍如何创建一个slub分配器的slab块

 

new_slab

 

    创建一个slab块。在slub分配器中,已经舍弃了struct slab结构,而是把一些必要的结构放入slab首页struct page中,这样首页struct page就可以表示一个slab,不再需要struct slab结构了。

static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)

{

       struct page *page;

       void *start;

       void *last;

       void *p;

 

       BUG_ON(flags & GFP_SLAB_BUG_MASK);

       /* 分配slab页面 */

       page = allocate_slab(s,

              flags & (GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node);

       if (!page)

              goto out;

       /* slab数加一 */

       inc_slabs_node(s, page_to_nid(page), page->objects);

       /* slab指针指向cache */

       page->slab = s;

       /* 表示此页块加入到slub分配器中 */

       page->flags |= 1 << PG_slab;

       /* 获得首页面的虚拟地址 */

       start = page_address(page);

       /* 调试相关,用POISON_INUSE填充slab */

       if (unlikely(s->flags & SLAB_POISON))

              memset(start, POISON_INUSE, PAGE_SIZE << compound_order(page));

 

       last = start;

       /* 遍历slab中的每个对象 */

       for_each_object(p, s, start, page->objects) {

              /* 初始化对象 */

              setup_object(s, page, last);

/* 设置下一个对象指针,将对象一个一个串联起来。这里对象指针直接放在对象后面,不再需要slab管理对象了。*/

              set_freepointer(s, last, p);

              last = p;

       }

       setup_object(s, page, last);

       /* 最后一个对象的下一个对象指针指向空 */

       set_freepointer(s, last, NULL);

       /* slabfeelist指针指向第一个空闲对象 */

       page->freelist = start;

       /* 已分配对象数为0 */

       page->inuse = 0;

out:

       return page;

}

 

allocate_slab

 

    分配slab占用的页块。

static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)

{

       struct page *page;

       struct kmem_cache_order_objects oo = s->oo;

       gfp_t alloc_gfp;

 

       flags |= s->allocflags;

 

       /*

        * Let the initial higher-order allocation fail under memory pressure

        * so we fall-back to the minimum order allocation.

        */

       alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL;

       /* 分配slab占用的页面 */

       page = alloc_slab_page(alloc_gfp, node, oo);

       /* 分配失败,调小order重试 */

       if (unlikely(!page)) {

              oo = s->min;

              /*

               * Allocation may have failed due to fragmentation.

               * Try a lower order alloc if possible

               */

              page = alloc_slab_page(flags, node, oo);

              if (!page)

                     return NULL;

 

              stat(s, ORDER_FALLBACK);

       }

       /* CONFIG_KMEMCHECK相关,内存检查相关,不去深究 */

       if (kmemcheck_enabled

              && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) {

              int pages = 1 << oo_order(oo);

 

              kmemcheck_alloc_shadow(page, oo_order(oo), flags, node);

 

              /*

               * Objects from caches that have a constructor don't get

               * cleared when they're allocated, so we need to do it here.

               */

              if (s->ctor)

                     kmemcheck_mark_uninitialized_pages(page, pages);

              else

                     kmemcheck_mark_unallocated_pages(page, pages);

       }

       /* 保存对象大小 */

       page->objects = oo_objects(oo);

       /* 更新页面统计 */

       mod_zone_page_state(page_zone(page),

              (s->flags & SLAB_RECLAIM_ACCOUNT) ?

              NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,

              1 << oo_order(oo));

 

       return page;

}

 

setup_object

    初始化对象。

 

static void setup_object(struct kmem_cache *s, struct page *page,

                            void *object)

{

       /* 为每个对象的存储区赋值,调试用 */

       setup_object_debug(s, page, object);

       /* 调用构造函数 */

       if (unlikely(s->ctor))

              s->ctor(object);

}

 

 set_freepointer

 

static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)

{

       /* 对象后面offset偏移处保存下一个空闲对象的指针 */

       *(void **)(object + s->offset) = fp;

}

 

阅读(701) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~