五、slab内存的释放


slab内存的释放在函数kmem_cache_free()中,主要处理部分在__cache_free()函数中,其代码解析如下:

  1. static inline void __cache_free(struct kmem_cache *cachep, void *objp)   
  2. {   
  3.     struct array_cache *ac = cpu_cache_get(cachep);   
  4.     check_irq_off();   
  5.     objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));   
  6.     if (cache_free_alien(cachep, objp))   
  7.         return;   
  8.     //本地高速缓存可用的空闲对象尚未达到限制,将空闲对象放入本地高速缓存   
  9.     if (likely(ac->avail < ac->limit)) {   
  10.         STATS_INC_FREEHIT(cachep);   
  11.         ac->entry[ac->avail++] = objp;   
  12.         return;   
  13.     } else {   
  14.         //cache_flusharray()会将本地高速缓存的一些空闲对象放入到slab中   
  15.         cache_flusharray(cachep, ac);   
  16.         ac->entry[ac->avail++] = objp;   
  17.     }   
  18. }   
  19.    
  20. static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)   
  21. {   
  22.     int batchcount;   
  23.     struct kmem_list3 *l3;   
  24.     int node = numa_node_id();   
  25.     //一次应该将batchcount个空闲对象归还到slab中   
  26.     batchcount = ac->batchcount;   
  27.     check_irq_off();   
  28.     //得到对应内存节点的slab list3,上面记录着该节点的slab链表   
  29.     l3 = cachep->nodelists[node];   
  30.     spin_lock(&l3->list_lock);   
  31.     //优先先归还到本地共享高速缓存中,注意本地共享高速缓存中的   
  32.     //空闲对象是仅供该内存节点上的各个cpu分配使用的,这样可以使内存访问的效率最高。   
  33.     if (l3->shared) {   
  34.         struct array_cache *shared_array = l3->shared;   
  35.         int max = shared_array->limit - shared_array->avail;   
  36.         if (max) {   
  37.             if (batchcount > max)   
  38.                 batchcount = max;   
  39.             //将batchcount个数组元素copy到本地高速缓存中   
  40.             memcpy(&(shared_array->entry[shared_array->avail]),   
  41.                    ac->entry, sizeof(void *) * batchcount);   
  42.             shared_array->avail += batchcount;   
  43.             goto free_done;   
  44.         }   
  45.     }   
  46.     //在没有本地高速缓存的情况下,释放回slab中   
  47.     free_block(cachep, ac->entry, batchcount, node);   
  48. free_done:   
  49.     spin_unlock(&l3->list_lock);   
  50.     ac->avail -batchcount;   
  51.     //将删除后剩下的空闲对象往前移动一下,hoho,可能还剩下些空闲对象   
  52.     memmove(ac->entry, &(ac->entry[batchcount]), sizeof(void *)*ac->avail);   
  53. }   
  54.    
  55. static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,   
  56.                int node)   
  57. {   
  58.     int i;   
  59.     struct kmem_list3 *l3;   
  60.    
  61.     for (i = 0; i < nr_objects; i++) {   
  62.         void *objp = objpp[i];   
  63.         struct slab *slabp;   
  64.         //先从对象获取到其所在的page,再从page得到其所属的slab   
  65.         //page->lru.prev中记录了page所属的slab   
  66.         slabp = virt_to_slab(objp);   
  67.         l3 = cachep->nodelists[node];   
  68.         list_del(&slabp->list);   
  69.         check_spinlock_acquired_node(cachep, node);   
  70.         check_slabp(cachep, slabp);   
  71.         //放入对应的slab   
  72.         slab_put_obj(cachep, slabp, objp, node);   
  73.         STATS_DEC_ACTIVE(cachep);   
  74.         l3->free_objects++;   
  75.         check_slabp(cachep, slabp);   
  76.    
  77.         /* fixup slab chains */   
  78.         //slab所有的对象都已经被归还   
  79.         if (slabp->inuse == 0) {   
  80.             //slab高速缓存的空闲对象数超过了限制,可以释放掉该slab,以   
  81.             //释放其所占有的内存   
  82.             if (l3->free_objects > l3->free_limit) {   
  83.                 l3->free_objects -cachep->num;   
  84.                 slab_destroy(cachep, slabp);   
  85.             } else {   
  86.                 //加入到完全空闲slab链表中   
  87.                 list_add(&slabp->list, &l3->slabs_free);   
  88.             }   
  89.         } else {   
  90.             //加入到部分空闲的slab链表中   
  91.             list_add_tail(&slabp->list, &l3->slabs_partial);   
  92.         }   
  93.     }   
  94. }  


相关内容