Linux内存管理--slab及其代码解析(1)(4)
五、slab内存的释放
slab内存的释放在函数kmem_cache_free()中,主要处理部分在__cache_free()函数中,其代码解析如下:
- static inline void __cache_free(struct kmem_cache *cachep, void *objp)
- {
- struct array_cache *ac = cpu_cache_get(cachep);
- check_irq_off();
- objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
- if (cache_free_alien(cachep, objp))
- return;
- //本地高速缓存可用的空闲对象尚未达到限制,将空闲对象放入本地高速缓存
- if (likely(ac->avail < ac->limit)) {
- STATS_INC_FREEHIT(cachep);
- ac->entry[ac->avail++] = objp;
- return;
- } else {
- //cache_flusharray()会将本地高速缓存的一些空闲对象放入到slab中
- cache_flusharray(cachep, ac);
- ac->entry[ac->avail++] = objp;
- }
- }
- static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
- {
- int batchcount;
- struct kmem_list3 *l3;
- int node = numa_node_id();
- //一次应该将batchcount个空闲对象归还到slab中
- batchcount = ac->batchcount;
- check_irq_off();
- //得到对应内存节点的slab list3,上面记录着该节点的slab链表
- l3 = cachep->nodelists[node];
- spin_lock(&l3->list_lock);
- //优先先归还到本地共享高速缓存中,注意本地共享高速缓存中的
- //空闲对象是仅供该内存节点上的各个cpu分配使用的,这样可以使内存访问的效率最高。
- if (l3->shared) {
- struct array_cache *shared_array = l3->shared;
- int max = shared_array->limit - shared_array->avail;
- if (max) {
- if (batchcount > max)
- batchcount = max;
- //将batchcount个数组元素copy到本地高速缓存中
- memcpy(&(shared_array->entry[shared_array->avail]),
- ac->entry, sizeof(void *) * batchcount);
- shared_array->avail += batchcount;
- goto free_done;
- }
- }
- //在没有本地高速缓存的情况下,释放回slab中
- free_block(cachep, ac->entry, batchcount, node);
- free_done:
- spin_unlock(&l3->list_lock);
- ac->avail -= batchcount;
- //将删除后剩下的空闲对象往前移动一下,hoho,可能还剩下些空闲对象
- memmove(ac->entry, &(ac->entry[batchcount]), sizeof(void *)*ac->avail);
- }
- static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
- int node)
- {
- int i;
- struct kmem_list3 *l3;
- for (i = 0; i < nr_objects; i++) {
- void *objp = objpp[i];
- struct slab *slabp;
- //先从对象获取到其所在的page,再从page得到其所属的slab
- //page->lru.prev中记录了page所属的slab
- slabp = virt_to_slab(objp);
- l3 = cachep->nodelists[node];
- list_del(&slabp->list);
- check_spinlock_acquired_node(cachep, node);
- check_slabp(cachep, slabp);
- //放入对应的slab
- slab_put_obj(cachep, slabp, objp, node);
- STATS_DEC_ACTIVE(cachep);
- l3->free_objects++;
- check_slabp(cachep, slabp);
- /* fixup slab chains */
- //slab所有的对象都已经被归还
- if (slabp->inuse == 0) {
- //slab高速缓存的空闲对象数超过了限制,可以释放掉该slab,以
- //释放其所占有的内存
- if (l3->free_objects > l3->free_limit) {
- l3->free_objects -= cachep->num;
- slab_destroy(cachep, slabp);
- } else {
- //加入到完全空闲slab链表中
- list_add(&slabp->list, &l3->slabs_free);
- }
- } else {
- //加入到部分空闲的slab链表中
- list_add_tail(&slabp->list, &l3->slabs_partial);
- }
- }
- }
评论暂时关闭