Linux Slab分配器(七)--销毁缓存

来源:互联网 发布:mp3刷机软件 编辑:程序博客网 时间:2024/06/06 08:53

水平有限,描述不当之处还请之处,转载请注明出处http://blog.csdn.net/vanbreaker/article/details/7674601

销毁缓存首先要保证的一点就是缓存当中所有的对象都是空闲的,也就是之前分配出去的对象都已经释放回来了,其主要的步骤如下

1.将缓存从cache_chain链表中删除

2.将本地高速缓存、alien高速缓存和共享本地高速缓存中的对象都释放回slab并释放所有的free链表,然后判断full链表以及partial链表是否都为空,如果有一个不为空说明存在非空闲slab,也就是说有对象还未释放,此时无法销毁缓存,重新将缓存添加到cache_chain链表中

3.确定所有的slab都为空闲状态后,将缓存涉及到的所有描述符都释放(这些描述符都是保存在普通高速缓存中的)

 

负责销毁缓存的函数为kmem_cache_destroy()

void kmem_cache_destroy(struct kmem_cache *cachep){BUG_ON(!cachep || in_interrupt());/* Find the cache in the chain of caches. */get_online_cpus();mutex_lock(&cache_chain_mutex);/* * the chain is never empty, cache_cache is never destroyed *//*将cache从cache_chain中删除*/list_del(&cachep->next);/*释放完free链表,如果FULL链表或partial链表中还有slab,说明还有对象处于分配状态因此不能销毁该缓存!*/if (__cache_shrink(cachep)) {slab_error(cachep, "Can't free all objects");/*重新将缓存添加到cache_chain链表中*/list_add(&cachep->next, &cache_chain);mutex_unlock(&cache_chain_mutex);put_online_cpus();return;}if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))rcu_barrier();/*释放cache所涉及到的各个描述符的存储对象*/__kmem_cache_destroy(cachep);mutex_unlock(&cache_chain_mutex);put_online_cpus();}


 

static int __cache_shrink(struct kmem_cache *cachep){int ret = 0, i = 0;struct kmem_list3 *l3;/*将本地高速缓存,share本地高速缓存以及alien高速缓存的空闲对象释放slab*/drain_cpu_caches(cachep);check_irq_on();for_each_online_node(i) {l3 = cachep->nodelists[i];if (!l3)continue;                  /*销毁空闲链表中的slab*/drain_freelist(cachep, l3, l3->free_objects);/*判断full和partial是否为空,有一个不为空则ret就为1*/ret += !list_empty(&l3->slabs_full) ||!list_empty(&l3->slabs_partial);}return (ret ? 1 : 0);}

drain_cpu_caches()的最终落脚在free_block()函数上,该函数在前面已做过分析,在此不再列出

 

static int drain_freelist(struct kmem_cache *cache,struct kmem_list3 *l3, int tofree){struct list_head *p;int nr_freed;struct slab *slabp;nr_freed = 0;/*slab中的对象还未释放完并且free链表不为空*/while (nr_freed < tofree && !list_empty(&l3->slabs_free)) {spin_lock_irq(&l3->list_lock);p = l3->slabs_free.prev;if (p == &l3->slabs_free) {/*链表中已无元素*/spin_unlock_irq(&l3->list_lock);goto out;}/*从free链表中取出一个slab*/slabp = list_entry(p, struct slab, list);#if DEBUGBUG_ON(slabp->inuse);#endif/*从链表中删除*/list_del(&slabp->list);/* * Safe to drop the lock. The slab is no longer linked * to the cache. */ /*空闲对象数量总数减去num*/l3->free_objects -= cache->num;spin_unlock_irq(&l3->list_lock);/*销毁slab*/slab_destroy(cache, slabp);nr_freed++;}out:return nr_freed;}

slab_destroy()函数已在前文中分析

 

static void __kmem_cache_destroy(struct kmem_cache *cachep){int i;struct kmem_list3 *l3;/*释放存储本地高速缓存描述符的对象*/for_each_online_cpu(i)    kfree(cachep->array[i]);/* NUMA: free the list3 structures */for_each_online_node(i) {l3 = cachep->nodelists[i];if (l3) {/*释放存储共享本地高速缓存描述符的对象*/kfree(l3->shared);/*释放存储alien本地高速缓存描述符的对象*/free_alien_cache(l3->alien);/*释放存储kmem_list3描述符的对象*/kfree(l3);}}/*释放存储缓存描述符的对象*/kmem_cache_free(&cache_cache, cachep);}


 


原创粉丝点击