Linux Slub分配器(二)--初始化 .

来源:互联网 发布:星际争霸 知乎 编辑:程序博客网 时间:2024/05/02 00:13

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

 

      和slab分配器一样,分配器的初始化工作主要是初始化用于kmalloc的gerneral cache,Slub分配器的gerneral cache定义如下:

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">struct kmem_cache kmalloc_caches[SLUB_PAGE_SHIFT] __cacheline_aligned;</SPAN>  
[cpp] view plaincopyprint?
  1. #define SLUB_PAGE_SHIFT (PAGE_SHIFT + 2)  


SLUB_PAGE_SHIFT的值为14,也就是说Slub分配器拥有14个gerneral cache,这14个gerneral cache的作用分别是什么呢?在NUMA架构下,下标为0的gc是用来存节点slab信息描述符的,也就是struct kmem_cache_node,UMA架构下,下标为0的gc被废弃。然后从下标为3的gc开始,缓存的对象大小从KMALLOC_MIN_SIZE开始按2的指数幂增长。那么下标为1和2的gc是用来做什么的呢?这两个gc是用来增加缓存的粒度的,下标为1的gc对应的缓存大小为96,下标为2的gc对应的缓存大小为192。当用kmalloc分配192字节以下的对象时,size_index数组用来选择在哪个gc中进行分配。

[cpp] view plaincopyprint?
  1. static s8 size_index[24] = {  
  2.     3,  /* 8 */  
  3.     4,  /* 16 */  
  4.     5,  /* 24 */  
  5.     5,  /* 32 */  
  6.     6,  /* 40 */  
  7.     6,  /* 48 */  
  8.     6,  /* 56 */  
  9.     6,  /* 64 */  
  10.     1,  /* 72 */  
  11.     1,  /* 80 */  
  12.     1,  /* 88 */  
  13.     1,  /* 96 */  
  14.     7,  /* 104 */  
  15.     7,  /* 112 */  
  16.     7,  /* 120 */  
  17.     7,  /* 128 */  
  18.     2,  /* 136 */  
  19.     2,  /* 144 */  
  20.     2,  /* 152 */  
  21.     2,  /* 160 */  
  22.     2,  /* 168 */  
  23.     2,  /* 176 */  
  24.     2,  /* 184 */  
  25.     2   /* 192 */  
  26. };  


size_index数组中存储的是gc的编号,要根据对象大小来定位gc的方法很简单,直接用size/8 - 1即可。如要分配大小为48的对象,那么48/8 - 1=5,而size_index数组中下标5对应的偏移为6,在kmalloc_caches数组中,下标6对应的gc的对象大小为64,因此就找到了一个合理的gc,当然,以上的讨论都是基于KMALLOC_MIN_SIZES为8的情况下的。那么可想而知,gc的初始化工作主要就是创建gc以及建立size_index数组到gc之间的映射。

 

[cpp] view plaincopyprint?
  1. <SPAN style="FONT-SIZE: 12px">void __init kmem_cache_init(void)  
  2. {  
  3.     int i;  
  4.     int caches = 0;  
  5.   
  6.     init_alloc_cpu();  
  7.   
  8. #ifdef CONFIG_NUMA   
  9.     /* 
  10.      * Must first have the slab cache available for the allocations of the 
  11.      * struct kmem_cache_node's. There is special bootstrap code in 
  12.      * kmem_cache_open for slab_state == DOWN. 
  13.      */  
  14.      /*创建kmalloc_caches的第0个缓存用来存储struct kmem_cache_node*/  
  15.     create_kmalloc_cache(&kmalloc_caches[0], "kmem_cache_node",  
  16.         sizeof(struct kmem_cache_node), GFP_NOWAIT);  
  17.     kmalloc_caches[0].refcount = -1;  
  18.     caches++;  
  19.   
  20.     hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);  
  21. #endif  
  22.   
  23.     /* Able to allocate the per node structures */  
  24.     slab_state = PARTIAL;//将初始化进度改为PARTIAL,表示已经可以分配struct kmem_cache_node  
  25.   
  26.     /* Caches that are not of the two-to-the-power-of size */  
  27.     /*如果kmalloc的最小对象大小不大于32则创建第1个缓存,对象大小为96字节*/  
  28.     if (KMALLOC_MIN_SIZE <= 32) {  
  29.         create_kmalloc_cache(&kmalloc_caches[1],  
  30.                 "kmalloc-96", 96, GFP_NOWAIT);  
  31.         caches++;  
  32.     }  
  33.     /*如果kmalloc的最小对象大小不大于64则创建第2个缓存,对象大小为192字节*/  
  34.     if (KMALLOC_MIN_SIZE <= 64) {  
  35.         create_kmalloc_cache(&kmalloc_caches[2],  
  36.                 "kmalloc-192", 192, GFP_NOWAIT);  
  37.         caches++;  
  38.     }  
  39.   
  40.     /*创建后续的普通缓存*/  
  41.     for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++) {  
  42.         create_kmalloc_cache(&kmalloc_caches[i],  
  43.             "kmalloc", 1 << i, GFP_NOWAIT);  
  44.         caches++;  
  45.     }  
  46.   
  47.   
  48.     /* 
  49.      * Patch up the size_index table if we have strange large alignment 
  50.      * requirements for the kmalloc array. This is only the case for 
  51.      * MIPS it seems. The standard arches will not generate any code here. 
  52.      * 
  53.      * Largest permitted alignment is 256 bytes due to the way we 
  54.      * handle the index determination for the smaller caches. 
  55.      * 
  56.      * Make sure that nothing crazy happens if someone starts tinkering 
  57.      * around with ARCH_KMALLOC_MINALIGN 
  58.      */  
  59.      /*这里做一些必要的检查,保证kmalloc允许的最小对象的大小不能大于256 
  60.        并且该值必须是2的整数幂*/  
  61.     BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||  
  62.         (KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));  
  63.   
  64.     /*对于大小在8字节与KMALLOC_MIN_SIZE之间的对象,将其在size_index数组中的索引 
  65.       设置为KMALLOC_SHIFT_LOW,也就是log(KMALLOC_MIN_SIZE),这些对象都将以KMALLOC_MIN_SIZE 
  66.       大小进行分配*/  
  67.     for (i = 8; i < KMALLOC_MIN_SIZE; i += 8) {  
  68.         int elem = size_index_elem(i);  
  69.         if (elem >= ARRAY_SIZE(size_index))  
  70.             break;  
  71.         size_index[elem] = KMALLOC_SHIFT_LOW;  
  72.     }  
  73.   
  74.     /*如果KMALLOC_MIN_SIZE为64,则弃用96字节的缓存*/  
  75.     if (KMALLOC_MIN_SIZE == 64) {  
  76.         /* 
  77.          * The 96 byte size cache is not used if the alignment 
  78.          * is 64 byte. 
  79.          */  
  80.          /*将72字节与96字节之间的对象子size_index数组中的索引设为7, 
  81.            这些对象将以128字节进行分配*/  
  82.         for (i = 64 + 8; i <= 96; i += 8)  
  83.             size_index[size_index_elem(i)] = 7;  
  84.     } else if (KMALLOC_MIN_SIZE == 128) {/*如果最小对象大小为128字节,则弃用192字节的缓存*/  
  85.         /* 
  86.          * The 192 byte sized cache is not used if the alignment 
  87.          * is 128 byte. Redirect kmalloc to use the 256 byte cache 
  88.          * instead. 
  89.          */  
  90.         for (i = 128 + 8; i <= 192; i += 8)  
  91.             size_index[size_index_elem(i)] = 8;  
  92.     }  
  93.   
  94.     slab_state = UP;//更新初始化进度  
  95.   
  96.     /* Provide the correct kmalloc names now that the caches are up */  
  97.     for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++)  
  98.         kmalloc_caches[i]. name =  
  99.             kasprintf(GFP_NOWAIT, "kmalloc-%d", 1 << i);  
  100.   
  101. #ifdef CONFIG_SMP  
  102.     register_cpu_notifier(&slab_notifier);  
  103.         /*计算kmem_cache的大小*/  
  104.     kmem_size = offsetof(struct kmem_cache, cpu_slab) +  
  105.                 nr_cpu_ids * sizeof(struct kmem_cache_cpu *);  
  106. #else   
  107.     kmem_size = sizeof(struct kmem_cache);  
  108. #endif   
  109.   
  110.     printk(KERN_INFO  
  111.         "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"  
  112.         " CPUs=%d, Nodes=%d\n",  
  113.         caches, cache_line_size(),  
  114.         slub_min_order, slub_max_order, slub_min_objects,  
  115.         nr_cpu_ids, nr_node_ids);  
  116. }</SPAN>  
0 0