static struct kmem_cache *create_kmalloc_cache(struct kmem_cache *s,
const char *name, int size, gfp_t gfp_flags)
{
unsigned int flags = 0;
if (gfp_flags & SLUB_DMA)
flags = SLAB_CACHE_DMA;
down_write(&slub_lock);
if (!kmem_cache_open(s, gfp_flags, name, size, ARCH_KMALLOC_MINALIGN,
flags, NULL))
goto panic;
list_add(&s->list, &slab_caches);
up_write(&slub_lock);
if (sysfs_slab_add(s))
goto panic;
return s;
panic:
panic("Creation of kmalloc slab %s size=%d failed./n", name, size);
}
static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
const char *name, size_t size,
size_t align, unsigned long flags,
void (*ctor)(struct kmem_cache *, void *))
{
memset(s, 0, kmem_size);
s->name = name;
s->ctor = ctor;
s->objsize = size;/*objsize 就是对象的实际大小 */
s->align = align;
s->flags = kmem_cache_flags(size, flags, name, ctor);
if (!calculate_sizes(s))/* 这个函数其实挺重要的,它将 kmem_cache -> offset 成员计算出来,这个成员的位置以后指明一个指针,该指针指向何处存放下一个空闲对象,对象后一般仅接着就是这个指针,但在需要对其的情况下,会往后移一些;该函数同时还计算出 kmem_cache -> size 成员,该成员表明一个对象实际在内存里面需要的长度,这个长度包括了对象本身的长度,其后指向下一个空闲对象的指针长度, SLUB Debug 的情况下,要加入一个空区域用于越界监管的长度,对齐所需长度等;然后,该函数再根据该 kmem_cache 的单个 SLAB 所包含的物理页面的数目 ( 放在了 kmem_cache->order 成员李,也是根据 kmem_cache -> size 算出来的 ) ,及单个对象的实际长度 kmem_cache -> size ,计算出来单个 SLAB 所能容纳的对象的个数,放在了 kmem_cache ->objects 成员里。 */
goto error;
s->refcount = 1;
#ifdef CONFIG_NUMA
s->defrag_ratio = 100;
#endif
if (!init_kmem_cache_nodes(s, gfpflags & ~SLUB_DMA))/* 这个函数只是初始化了 kmem_cache -> local_node 成员,比如其 nr_partial 赋 0 ,表示没有 Partial SLAB 在上面 */
goto error;
if (alloc_kmem_cache_cpus(s, gfpflags & ~SLUB_DMA)) /* 这个函数只是初始化了 kmem_cache ->kmem_cache_cpu 成员,比如其 kmem_cache_cpu 赋 NULL ,表示没有当前 SLAB*/
return 1;
free_kmem_cache_nodes(s);
error:
if (flags & SLAB_PANIC)
panic("Cannot create slab %s size=%lu realsize=%u "
"order=%u offset=%u flags=%lx/n",
s->name, (unsigned long)size, s->size, s->order,
s->offset, flags);
return 0;
}
本文深入探讨了Linux内核中SLUB内存分配器的工作原理,重点介绍了create_kmalloc_cache和kmem_cache_open函数的实现细节,包括内存缓存创建过程、对象大小计算以及内存对齐处理等内容。
2578

被折叠的 条评论
为什么被折叠?



