Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1504103
  • 博文数量: 228
  • 博客积分: 1698
  • 博客等级: 上尉
  • 技术积分: 3241
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-24 21:49
个人简介

Linux

文章分类

全部博文(228)

文章存档

2017年(1)

2016年(43)

2015年(102)

2014年(44)

2013年(5)

2012年(30)

2011年(3)

分类: LINUX

2015-01-18 14:17:19

上文分析了普通对象的申请过程,kmalloc。现在看一下针对专用对象的申请kmem_cache_alloc函数。

点击(此处)折叠或打开

  1. /**
  2.  * kmem_cache_alloc - Allocate an object
  3.  * @cachep: The cache to allocate from.
  4.  * @flags: See kmalloc().
  5.  *
  6.  * Allocate an object from this cache. The flags are only relevant
  7.  * if the cache has no available objects.
  8.  */
  9. void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
  10. {
        /* __builtin_return_address是GCC内置函数,用于获取当前函数的返回地址 */
  11.     void *ret = __cache_alloc(cachep, flags, __builtin_return_address(0));

  12.     trace_kmem_cache_alloc(_RET_IP_, ret,
  13.              obj_size(cachep), cachep->buffer_size, flags);

  14.     return ret;
  15. }

点击(此处)折叠或打开

  1. __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
  2. {
  3.     unsigned long save_flags;
  4.     void *objp;

  5.     flags &= gfp_allowed_mask;

  6.     lockdep_trace_alloc(flags);

  7.     if (slab_should_failslab(cachep, flags))
  8.         return NULL;

  9.     cache_alloc_debugcheck_before(cachep, flags);
  10.     local_irq_save(save_flags);
  11.     /* 在关硬中断的前提下,调用下面函数,完成实际的分配过程 */
  12.     objp = __do_cache_alloc(cachep, flags);
  13.     local_irq_restore(save_flags);
  14.     objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
  15.     kmemleak_alloc_recursive(objp, obj_size(cachep), 1, cachep->flags,
  16.                  flags);
  17.     prefetchw(objp);

  18.     if (likely(objp))
  19.         kmemcheck_slab_alloc(cachep, flags, objp, obj_size(cachep));

  20.     if (unlikely((flags & __GFP_ZERO) && objp))
  21.         memset(objp, 0, obj_size(cachep));

  22.     return objp;
  23. }
__do_cache_alloc在开启NUMA和不开启NUMA时定义不同,简单起见,假设为UMA

点击(此处)折叠或打开

  1. static __always_inline void *
  2. __do_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
  3. {
  4.     return ____cache_alloc(cachep, flags);
  5. }

点击(此处)折叠或打开

  1. static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
  2. {
  3.     void *objp;
  4.     struct array_cache *ac;

  5.     check_irq_off();
  6.     /* 获取local cache, array_cache数组 */
  7.     ac = cpu_cache_get(cachep);
  8.     /* 有空闲对象 */
  9.     if (likely(ac->avail)) {
  10.         STATS_INC_ALLOCHIT(cachep);
  11.         /* 标示最近被访问 */
  12.         ac->touched = 1;
  13.         /* 分配一个对象,avail指向可用的空闲节点 */
  14.         objp = ac->entry[--ac->avail];
  15.     } else {
  16.         STATS_INC_ALLOCMISS(cachep);
  17.         /* local cache中无空闲对象,填充 */
  18.         objp = cache_alloc_refill(cachep, flags);
  19.     }
  20.     /*
  21.      * To avoid a false negative, if an object that is in one of the
  22.      * per-CPU caches is leaked, we need to make sure kmemleak doesn't
  23.      * treat the array pointers as a reference to the object.
  24.      */
  25.     kmemleak_erase(&ac->entry[ac->avail]);
  26.     return objp;
  27. }
以上整个过程与kmalloc实际上是相同的,只是对外提供了两种不同的API,cache_calloc_refill前面已经分析了,不再赘述。



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