Linux内存管理之slab机制(分配对象)

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中查找是否有空闲的对象;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/22824.html