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


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

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

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

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

相关阅读:

Linux Slab分配器(一)--概述
Linux Slab分配器(二)--初始化
Linux Slab分配器(三)--创建缓存
Linux Slab分配器(四)--分配对象
Linux Slab分配器(五)--释放对象
Linux Slab分配器(六)--创建slab和销毁slab

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

  1. void kmem_cache_destroy(struct kmem_cache *cachep)  
  2. {  
  3.     BUG_ON(!cachep || in_interrupt());  
  4.   
  5.     /* Find the cache in the chain of caches. */  
  6.     get_online_cpus();  
  7.     mutex_lock(&cache_chain_mutex);  
  8.     /* 
  9.      * the chain is never empty, cache_cache is never destroyed 
  10.      */  
  11.     /*将cache从cache_chain中删除*/  
  12.     list_del(&cachep->next);  
  13.       
  14.     /*释放完free链表,如果FULL链表或partial链表中还有slab,说明还有对象处于分配状态 
  15.     因此不能销毁该缓存!*/  
  16.     if (__cache_shrink(cachep)) {  
  17.         slab_error(cachep, "Can't free all objects");  
  18.         /*重新将缓存添加到cache_chain链表中*/  
  19.         list_add(&cachep->next, &cache_chain);  
  20.         mutex_unlock(&cache_chain_mutex);  
  21.         put_online_cpus();  
  22.         return;  
  23.     }  
  24.   
  25.     if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))  
  26.         rcu_barrier();  
  27.   
  28.     /*释放cache所涉及到的各个描述符的存储对象*/  
  29.     __kmem_cache_destroy(cachep);  
  30.     mutex_unlock(&cache_chain_mutex);  
  31.     put_online_cpus();  
  32. }  

 

 
  1. static int __cache_shrink(struct kmem_cache *cachep)  
  2. {  
  3.     int ret = 0, i = 0;  
  4.     struct kmem_list3 *l3;  
  5.   
  6.     /*将本地高速缓存,share本地高速缓存以及alien高速缓存的空闲对象释放slab*/  
  7.     drain_cpu_caches(cachep);  
  8.   
  9.     check_irq_on();  
  10.     for_each_online_node(i) {  
  11.         l3 = cachep->nodelists[i];  
  12.         if (!l3)  
  13.             continue;  
  14.                   /*销毁空闲链表中的slab*/  
  15.         drain_freelist(cachep, l3, l3->free_objects);  
  16.   
  17.         /*判断full和partial是否为空,有一个不为空则ret就为1*/  
  18.         ret += !list_empty(&l3->slabs_full) ||  
  19.             !list_empty(&l3->slabs_partial);  
  20.     }  
  21.     return (ret ? 1 : 0);  
  22. }  
  • 1
  • 2
  • 下一页

相关内容