Linux内存管理之slab分配器分析(四 申请对象 kmem_cache_alloc)

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

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

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

    return ret;
}
__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
{
    unsigned long save_flags;
    void *objp;

    flags &= gfp_allowed_mask;

    lockdep_trace_alloc(flags);

    if (slab_should_failslab(cachep, flags))
        return NULL;

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

    if (likely(objp))
        kmemcheck_slab_alloc(cachep, flags, objp, obj_size(cachep));

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

    return objp;
}

__do_cache_alloc在开启NUMA和不开启NUMA时定义不同,简单起见,假设为UMA

static __always_inline void *
__do_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
{
    return ____cache_alloc(cachep, flags);
}
static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
{
    void *objp;
    struct array_cache *ac;

    check_irq_off();
    /* 获取local cache, array_cache数组 */
    ac = cpu_cache_get(cachep);
    /* 有空闲对象 */
    if (likely(ac->avail)) {
        STATS_INC_ALLOCHIT(cachep);
        /* 标示最近被访问 */
        ac->touched = 1;
        /* 分配一个对象,avail指向可用的空闲节点 */
        objp = ac->entry[--ac->avail];
    } else {
        STATS_INC_ALLOCMISS(cachep);
        /* local cache中无空闲对象,填充 */
        objp = cache_alloc_refill(cachep, flags);
    }
    /*
     * To avoid a false negative, if an object that is in one of the
     * per-CPU caches is leaked, we need to make sure kmemleak doesn't
     * treat the array pointers as a reference to the object.
     */
    kmemleak_erase(&ac->entry[ac->avail]);
    return objp;
}

以上整个过程与kmalloc实际上是相同的,只是对外提供了两种不同的API,cache_calloc_refill前面已经分析了,不再赘述。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值