歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux Slab分配器(六)--創建slab和銷毀slab

在滿足以下兩個條件時,slab分配器將為高速緩存創建新的slab

1.請求分配對象,但本地高速緩存沒有空閒對象可以分配,需要填充

2.kmem_list3維護的鏈表中沒有slab或者所有的slab都處於FULL鏈表中

這時,調用cache_grow()創建slab增大緩存容量

相關閱讀:

Linux Slab分配器(一)--概述 http://www.linuxidc.com/Linux/2012-06/62965.htm
Linux Slab分配器(二)--初始化 http://www.linuxidc.com/Linux/2012-06/62966.htm
Linux Slab分配器(三)--創建緩存 http://www.linuxidc.com/Linux/2012-06/63109.htm
Linux Slab分配器(四)--分配對象 http://www.linuxidc.com/Linux/2012-06/63138.htm

下圖給出了cache_grow()的代碼流程

 

  1. static int cache_grow(struct kmem_cache *cachep,  
  2.         gfp_t flags, int nodeid, void *objp)  
  3. {  
  4.     struct slab *slabp;  
  5.     size_t offset;  
  6.     gfp_t local_flags;  
  7.     struct kmem_list3 *l3;  
  8.   
  9.     /* 
  10.      * Be lazy and only check for valid flags here,  keeping it out of the 
  11.      * critical path in kmem_cache_alloc(). 
  12.      */  
  13.     BUG_ON(flags & GFP_SLAB_BUG_MASK);  
  14.     local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);  
  15.   
  16.     /* Take the l3 list lock to change the colour_next on this node */  
  17.     check_irq_off();  
  18.     l3 = cachep->nodelists[nodeid];  
  19.     spin_lock(&l3->list_lock);  
  20.   
  21.     /* Get colour for the slab, and cal the next value. */  
  22.     /*確定待創建的slab的顏色編號*/  
  23.     offset = l3->colour_next;  
  24.     /*更新下一個slab的顏色編號*/  
  25.     l3->colour_next++;  
  26.     /*顏色編號必須小於顏色數*/  
  27.     if (l3->colour_next >= cachep->colour)  
  28.         l3->colour_next = 0;  
  29.     spin_unlock(&l3->list_lock);  
  30.   
  31.     /*確定待創建的slab的顏色*/  
  32.     offset *= cachep->colour_off;  
  33.   
  34.     if (local_flags & __GFP_WAIT)  
  35.         local_irq_enable();  
  36.   
  37.     /* 
  38.      * The test for missing atomic flag is performed here, rather than 
  39.      * the more obvious place, simply to reduce the critical path length 
  40.      * in kmem_cache_alloc(). If a caller is seriously mis-behaving they 
  41.      * will eventually be caught here (where it matters). 
  42.      */  
  43.     kmem_flagcheck(cachep, flags);  
  44.   
  45.     /* 
  46.      * Get mem for the objs.  Attempt to allocate a physical page from 
  47.      * 'nodeid'. 
  48.      */  
  49.     if (!objp)  
  50.         /*從伙伴系統分配頁框,這是slab分配器與伙伴系統的接口*/  
  51.         objp = kmem_getpages(cachep, local_flags, nodeid);  
  52.     if (!objp)  
  53.         goto failed;  
  54.   
  55.     /* Get slab management. */  
  56.     /*分配slab管理區*/  
  57.     slabp = alloc_slabmgmt(cachep, objp, offset,  
  58.             local_flags & ~GFP_CONSTRAINT_MASK, nodeid);  
  59.     if (!slabp)  
  60.         goto opps1;  
  61.   
  62.     /*建立頁面到slab和cache的映射,以便於根據obj迅速定位slab描述符和cache描述符*/  
  63.     slab_map_pages(cachep, slabp, objp);  
  64.   
  65.     /*初始化對象*/  
  66.     cache_init_objs(cachep, slabp);  
  67.   
  68.     if (local_flags & __GFP_WAIT)  
  69.         local_irq_disable();  
  70.     check_irq_off();  
  71.     spin_lock(&l3->list_lock);  
  72.   
  73.     /* Make slab active. */  
  74.     /*將新創建的slab添加到free鏈表*/  
  75.     list_add_tail(&slabp->list, &(l3->slabs_free));  
  76.     STATS_INC_GROWN(cachep);  
  77.     l3->free_objects += cachep->num;  
  78.     spin_unlock(&l3->list_lock);  
  79.     return 1;  
  80. opps1:  
  81.     kmem_freepages(cachep, objp);  
  82. failed:  
  83.     if (local_flags & __GFP_WAIT)  
  84.         local_irq_disable();  
  85.     return 0;  
  86. }  
Copyright © Linux教程網 All Rights Reserved