水平有限,描述不当之处还请之处,转载请注明出处http://blog.csdn.net/vanbreaker/article/details/7695264
和slab分配器一样,分配器的初始化工作主要是初始化用于kmalloc的gerneral cache,Slub分配器的gerneral cache定义如下:
- <SPAN style="FONT-SIZE: 12px">struct kmem_cache kmalloc_caches[SLUB_PAGE_SHIFT] __cacheline_aligned;</SPAN>
<span style="font-size:12px;">struct kmem_cache kmalloc_caches[SLUB_PAGE_SHIFT] __cacheline_aligned;</span>
- #define SLUB_PAGE_SHIFT (PAGE_SHIFT + 2)
#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中进行分配。
- static s8 size_index[24] = {
- 3, /* 8 */
- 4, /* 16 */
- 5, /* 24 */
- 5, /* 32 */
- 6, /* 40 */
- 6, /* 48 */
- 6, /* 56 */
- 6, /* 64 */
- 1, /* 72 */
- 1, /* 80 */
- 1, /* 88 */
- 1, /* 96 */
- 7, /* 104 */
- 7, /* 112 */
- 7, /* 120 */
- 7, /* 128 */
- 2, /* 136 */
- 2, /* 144 */
- 2, /* 152 */
- 2, /* 160 */
- 2, /* 168 */
- 2, /* 176 */
- 2, /* 184 */
- 2 /* 192 */
- };
static s8 size_index[24] = {
3, /* 8 */
4, /* 16 */
5, /* 24 */
5, /* 32 */
6, /* 40 */
6, /* 48 */
6, /* 56 */
6, /* 64 */
1, /* 72 */
1, /* 80 */
1, /* 88 */
1, /* 96 */
7, /* 104 */
7, /* 112 */
7, /* 120 */
7, /* 128 */
2, /* 136 */
2, /* 144 */
2, /* 152 */
2, /* 160 */
2, /* 168 */
2, /* 176 */
2, /* 184 */
2 /* 192 */
};
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之间的映射。
- <SPAN style="FONT-SIZE: 12px">void __init kmem_cache_init(void)
- {
- int i;
- int caches = 0;
- init_alloc_cpu();
- #ifdef CONFIG_NUMA
- /*
- * Must first have the slab cache available for the allocations of the
- * struct kmem_cache_node's. There is special bootstrap code in
- * kmem_cache_open for slab_state == DOWN.
- */
- /*创建kmalloc_caches的第0个缓存用来存储struct kmem_cache_node*/
- create_kmalloc_cache(&kmalloc_caches[0], "kmem_cache_node",
- sizeof(struct kmem_cache_node), GFP_NOWAIT);
- kmalloc_caches[0].refcount = -1;
- caches++;
- hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);
- #endif
- /* Able to allocate the per node structures */
- slab_state = PARTIAL;//将初始化进度改为PARTIAL,表示已经可以分配struct kmem_cache_node
- /* Caches that are not of the two-to-the-power-of size */
- /*如果kmalloc的最小对象大小不大于32则创建第1个缓存,对象大小为96字节*/
- if (KMALLOC_MIN_SIZE <= 32) {
- create_kmalloc_cache(&kmalloc_caches[1],
- "kmalloc-96", 96, GFP_NOWAIT);
- caches++;
- }
- /*如果kmalloc的最小对象大小不大于64则创建第2个缓存,对象大小为192字节*/
- if (KMALLOC_MIN_SIZE <= 64) {
- create_kmalloc_cache(&kmalloc_caches[2],
- "kmalloc-192", 192, GFP_NOWAIT);
- caches++;
- }
- /*创建后续的普通缓存*/
- for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++) {
- create_kmalloc_cache(&kmalloc_caches[i],
- "kmalloc", 1 << i, GFP_NOWAIT);
- caches++;
- }
- /*
- * Patch up the size_index table if we have strange large alignment
- * requirements for the kmalloc array. This is only the case for
- * MIPS it seems. The standard arches will not generate any code here.
- *
- * Largest permitted alignment is 256 bytes due to the way we
- * handle the index determination for the smaller caches.
- *
- * Make sure that nothing crazy happens if someone starts tinkering
- * around with ARCH_KMALLOC_MINALIGN
- */
- /*这里做一些必要的检查,保证kmalloc允许的最小对象的大小不能大于256
- 并且该值必须是2的整数幂*/
- BUILD_BUG_ON(KMALLOC_MIN_SIZE > 256 ||
- (KMALLOC_MIN_SIZE & (KMALLOC_MIN_SIZE - 1)));
- /*对于大小在8字节与KMALLOC_MIN_SIZE之间的对象,将其在size_index数组中的索引
- 设置为KMALLOC_SHIFT_LOW,也就是log(KMALLOC_MIN_SIZE),这些对象都将以KMALLOC_MIN_SIZE
- 大小进行分配*/
- for (i = 8; i < KMALLOC_MIN_SIZE; i += 8) {
- int elem = size_index_elem(i);
- if (elem >= ARRAY_SIZE(size_index))
- break;
- size_index[elem] = KMALLOC_SHIFT_LOW;
- }
- /*如果KMALLOC_MIN_SIZE为64,则弃用96字节的缓存*/
- if (KMALLOC_MIN_SIZE == 64) {
- /*
- * The 96 byte size cache is not used if the alignment
- * is 64 byte.
- */
- /*将72字节与96字节之间的对象子size_index数组中的索引设为7,
- 这些对象将以128字节进行分配*/
- for (i = 64 + 8; i <= 96; i += 8)
- size_index[size_index_elem(i)] = 7;
- } else if (KMALLOC_MIN_SIZE == 128) {/*如果最小对象大小为128字节,则弃用192字节的缓存*/
- /*
- * The 192 byte sized cache is not used if the alignment
- * is 128 byte. Redirect kmalloc to use the 256 byte cache
- * instead.
- */
- for (i = 128 + 8; i <= 192; i += 8)
- size_index[size_index_elem(i)] = 8;
- }
- slab_state = UP;//更新初始化进度
- /* Provide the correct kmalloc names now that the caches are up */
- for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++)
- kmalloc_caches[i]. name =
- kasprintf(GFP_NOWAIT, "kmalloc-%d", 1 << i);
- #ifdef CONFIG_SMP
- register_cpu_notifier(&slab_notifier);
- /*计算kmem_cache的大小*/
- kmem_size = offsetof(struct kmem_cache, cpu_slab) +
- nr_cpu_ids * sizeof(struct kmem_cache_cpu *);
- #else
- kmem_size = sizeof(struct kmem_cache);
- #endif
- printk(KERN_INFO
- "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
- " CPUs=%d, Nodes=%d\n",
- caches, cache_line_size(),
- slub_min_order, slub_max_order, slub_min_objects,
- nr_cpu_ids, nr_node_ids);
- }</SPAN>