Linux Slub分配器(六)--slab的分配与释放

来源:互联网 发布:nginx 系统 日志 编辑:程序博客网 时间:2024/05/02 04:51

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

       创建新的slab主要有两个工作,一个是从伙伴系统分配2^order个连续页框给该slab,然后就是划分slab中的对象。

函数new_slab()用来创建一个新的slab.

       

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)  
  2. {  
  3.     struct page *page;  
  4.     void *start;  
  5.     void *last;  
  6.     void *p;  
  7.   
  8.     BUG_ON(flags & GFP_SLAB_BUG_MASK);  
  9.   
  10.     /*为待创建的slab分配页框*/  
  11.     page = allocate_slab(s,  
  12.         flags & (GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node);  
  13.     if (!page)  
  14.         goto out;  
  15.       
  16.     /*增加slab计数*/  
  17.     inc_slabs_node(s, page_to_nid(page), page->objects);  
  18.   
  19.     page->slab = s;//设置页描述符的slab指针  
  20.     page->flags |= 1 << PG_slab;//为页框增加一个slab属性  
  21.     if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |  
  22.             SLAB_STORE_USER | SLAB_TRACE))  
  23.         __SetPageSlubDebug(page);  
  24.   
  25.     /*获取页框的虚拟地址*/  
  26.     start = page_address(page);  
  27.   
  28.     if (unlikely(s->flags & SLAB_POISON))  
  29.         memset(start, POISON_INUSE, PAGE_SIZE << compound_order(page));  
  30.   
  31.     last = start;  
  32.     for_each_object(p, s, start, page->objects) {  
  33.         setup_object(s, page, last);//调用构造函数  
  34.         set_freepointer(s, last, p); //设置空闲指针,即last后面的空闲对象为p  
  35.         last = p;  
  36.     }  
  37.     setup_object(s, page, last);  
  38.     set_freepointer(s, last, NULL);  //最后一个对象的空闲指针设为NULL  
  39.   
  40.     /*设置page的freelist和inuse*/  
  41.     page->freelist = start;  
  42.     page->inuse = 0;  
  43. out:  
  44.     return page;  
  45. }</SPAN>  

 

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)  
  2. {  
  3.     struct page *page;  
  4.     struct kmem_cache_order_objects oo = s->oo;  
  5.     gfp_t alloc_gfp;  
  6.   
  7.     flags |= s->allocflags;  
  8.   
  9.     /* 
  10.      * Let the initial higher-order allocation fail under memory pressure 
  11.      * so we fall-back to the minimum order allocation. 
  12.      */  
  13.      /*确定gfp标识*/  
  14.     alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL;  
  15.   
  16.     /*分配页框*/  
  17.     page = alloc_slab_page(alloc_gfp, node, oo);  
  18.   
  19.     /*如果分配失败,则按min的标准进行分配*/  
  20.     if (unlikely(!page)) {  
  21.         oo = s->min;  
  22.         /* 
  23.          * Allocation may have failed due to fragmentation. 
  24.          * Try a lower order alloc if possible 
  25.          */  
  26.         page = alloc_slab_page(flags, node, oo);  
  27.         if (!page)  
  28.             return NULL;  
  29.   
  30.         stat(get_cpu_slab(s, raw_smp_processor_id()), ORDER_FALLBACK);  
  31.     }  
  32.   
  33.     if (kmemcheck_enabled  
  34.         && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) {  
  35.         int pages = 1 << oo_order(oo);  
  36.   
  37.         kmemcheck_alloc_shadow(page, oo_order(oo), flags, node);  
  38.   
  39.         /* 
  40.          * Objects from caches that have a constructor don't get 
  41.          * cleared when they're allocated, so we need to do it here. 
  42.          */  
  43.         if (s->ctor)  
  44.             kmemcheck_mark_uninitialized_pages(page, pages);  
  45.         else  
  46.             kmemcheck_mark_unallocated_pages(page, pages);  
  47.     }  
  48.   
  49.       
  50.     page->objects = oo_objects(oo);//从oo中提取出slab中的对象数放到保存到page的objects中  
  51.     mod_zone_page_state(page_zone(page),  
  52.         (s->flags & SLAB_RECLAIM_ACCOUNT) ?  
  53.         NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,  
  54.         1 << oo_order(oo));  
  55.   
  56.     return page;  
  57. }</SPAN>  


函数alloc_slab_page()便是Slub分配器与伙伴系统的接口!

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">static inline struct page *alloc_slab_page(gfp_t flags, int node,  
  2.                     struct kmem_cache_order_objects oo)  
  3. {  
  4.     int order = oo_order(oo);//从oo中提取出分配阶数  
  5.   
  6.     flags |= __GFP_NOTRACK;  
  7.   
  8.     /*从伙伴系统中分配2^order个连续页框*/  
  9.     if (node == -1)  
  10.         return alloc_pages(flags, order);  
  11.     else  
  12.         return alloc_pages_node(node, flags, order);  
  13. }  
  14. </SPAN>  



获得了所需的页框后,接下来就是在这些页框中划分对象,将他们全部组织起来

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">for_each_object(p, s, start, page->objects) {  
  2.         setup_object(s, page, last);//调用构造函数  
  3.         set_freepointer(s, last, p); //设置空闲指针,即last后面的空闲对象为p  
  4.         last = p;  
  5.     }  
  6. </SPAN>  


 

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">#define for_each_object(__p, __s, __addr, __objects) \  
  2.     for (__p = (__addr); __p < (__addr) + (__objects) * (__s)->size;\  
  3.             __p += (__s)->size)  
  4. </SPAN>  


 

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)  
  2. {  
  3.     /*注意kmem_cache中的offset是以字节为单位的*/  
  4.     *(void **)(object + s->offset) = fp;  
  5. }  
  6. </SPAN>  


 

初始化后的对象如下图所示

 

销毁slab通过函数discard_slab()来完成

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">static void discard_slab(struct kmem_cache *s, struct page *page)  
  2. {  
  3.     /*减少节点的slab计数和对象计数*/  
  4.     dec_slabs_node(s, page_to_nid(page), page->objects);  
  5.     free_slab(s, page);//释放slab  
  6. }</SPAN>  

 

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">static void free_slab(struct kmem_cache *s, struct page *page)  
  2. {  
  3.     if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) {  
  4.         /* 
  5.          * RCU free overloads the RCU head over the LRU 
  6.          */  
  7.         struct rcu_head *head = (void *)&page->lru;  
  8.   
  9.         call_rcu(head, rcu_free_slab);//通过RCU方式来释放  
  10.     } else  
  11.         __free_slab(s, page);//将slab所占页框释放回伙伴系统  
  12. }  
  13. </SPAN>  



 

0 0
原创粉丝点击