Linux内核从slab中分配内存空间上层函数由kmalloc()或kmem_cache_alloc()函数实现。
kmalloc()->__kmalloc()->__do_kmalloc()
/** * __do_kmalloc - allocate memory * @size: how many bytes of memory are required. * @flags: the type of memory to allocate (see kmalloc). * @caller: function caller for debug tracking of the caller */ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, void *caller) { struct kmem_cache *cachep; void *ret; /* If you want to save a few bytes .text space: replace * __ with kmem_. * Then kmalloc uses the uninlined functions instead of the inline * functions. */ /*查找指定大小的通用cache,关于sizes[]数组,在前面 的初始化中就已经分析过了*/ cachep = __find_general_cachep(size, flags); if (unlikely(ZERO_OR_NULL_PTR(cachep))) return cachep; /*实际的分配工作*/ ret = __cache_alloc(cachep, flags, caller); trace_kmalloc((unsigned long) caller, ret, size, cachep->buffer_size, flags); return ret; }
实际的分配工作:__do_cache_alloc()->__cache_alloc()->____cache_alloc()
/*从指定cache中分配对象*/ static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) { void *objp; struct array_cache *ac; check_irq_off(); /* 获得本CPU的local cache */ ac = cpu_cache_get(cachep); /* 如果local cache中有可用的空闲对象 */ if (likely(ac->avail)) { /* 更新local cache命中计数 */ STATS_INC_ALLOCHIT(cachep); /* touched置1表示最近使用了local cache,这会影响填充 local cache时的数目,最近使用的填充较多的对象 */ ac->touched = 1; /* 从local cache的entry数组中提取最后面的空闲对象 */ objp = ac->entry[--ac->avail]; } else { /* local cache中没有空闲对象,更新未命中计数 */ STATS_INC_ALLOCMISS(cachep); /* 从slab三链中提取空闲对象填充到local cache中 */ objp = cache_alloc_refill(cachep, flags); #if 0/*这里是我新加的,这里可能是这个版本的一个bug,在最新的内核里面这块已经加上了*/ /* * the 'ac' may be updated by cache_alloc_refill(), * and kmemleak_erase() requires its correct value. */ /* cache_alloc_refill的cache_grow打开了中断,local cache指针可能发生了变化,需要重新获得 */ ac = cpu_cache_get(cachep); #endif } /* * 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. */ /* 分配出去的对象,其entry指针指向空 */ kmemleak_erase(&ac->entry[ac->avail]); return objp; }
该函数的执行流程:
1,从本地CPU cache中查找是否有空闲的对象;