slab内存分配器初始化有函数kmem_cache_init来完成,本文会详细介绍slab内存分配器的初始化流程。
软件架构
kmem_cache_init
|----->kmem_cache = &kmem_cache_boot;
| 第一个kmem cache实例,静态定义,不过尚需必须要的初始化
|----->kmem_cache_node_init(&init_kmem_cache_node[i]);
| 初始化静态定义的struct kmem_cache_node实例,这里有两个node实例;它们是分别为前两个
| kmem cache实例准备的,第一个kmem cache实例用于为创建其他kmem cache实例分配空间,
| 第二个kmem cache实例用于为创建struct kmem_cache_node实例分配空间,所以前两个kmem cache
| 实例需要静态分配struct kmem_cache_node实例。
|----->create_boot_cache(kmem_cache, "kmem_cache", offsetof(struct kmem_cache, node) +
| nr_node_ids * sizeof(struct kmem_cache_node *),SLAB_HWCACHE_ALIGN);
| 完成第一个kmem cache实例kmem_cache的初始化,第三个参数很重要,是该kmem cache实例所维护
| 的object的size。
| |----->s->size = s->object_size = size;
| | 设置object size
| |----->s->align = calculate_alignment(flags, ARCH_KMALLOC_MINALIGN, size);
| | 计算按多少字节对齐,详见重要函数分析。
| |----->err = __kmem_cache_create(s, flags);
| | |----->set_objfreelist_slab_cache(cachep, size, flags)
| | | |----->left = calculate_slab_order(cachep, size, flags | CFLGS_OBJFREELIST_SLAB);
| | | | 计算该kmem cache实例对应的slab order,原则是slab尽量小,浪费尽量少,详见重要函数分析。
| | | | 这里没有设置CFLGS_OFF_SLAB,是因为还没有创建freelist index的kmem cache实例,freelist
| | | | 只能存放在slab内。
| | |----->cachep->freelist_size = cachep->num * sizeof(freelist_idx_t);
| | | freelist index占用空间大小
| | |----->err = setup_cpu_cache(cachep, gfp);
| | | |----->cachep->cpu_cache = alloc_kmem_cache_cpus(cachep, 1, 1);
| | | | 分配array_cache实例
| | | |----->set_up_node(kmem_cache, CACHE_CACHE);
| | | | 设置node
| | | |----->cpu_cache_get(cachep)->avail = 0;
| | | | 由于还没有申请slab,不存在可用的object,所以可用的object为0
|----->list_add(&kmem_cache->list, &slab_caches);
| kmem cache实例加入slab_caches链表
|----->slab_state = PARTIAL;
|----->kmalloc_caches[INDEX_NODE] = create_kmalloc_cache("kmalloc-node",
| kmalloc_size(INDEX_NODE), ARCH_KMALLOC_FLAGS);
| 创建第二个kmem cache实例,从object size可以看出,该实例用于为struct kmem_cache_node分配空间。
| 指针数组kmalloc_caches是kmalloc用的kmem cache实例数组,该数组十分重要,详见重要变量分析。
| |----->struct kmem_cache *s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
| | 从kmem cache kmem_cache中分配一个object
| | |----->return kmem_cache_alloc(k, flags | __GFP_ZERO);
| | | |----->void *ret = slab_alloc(cachep, flags, _RET_IP_);
| | | | |----->objp = __do_cache_alloc(cachep, flags);
| | | | | 分配一个object,该函数比较复杂,详情请参考重要函数分析
| |----->create_boot_cache(s, name, size, flags);
| |----->list_add(&s->list, &slab_caches);
|----->slab_state = PARTIAL_NODE;
|----->setup_kmalloc_cache_index_table();
|----->init_list(kmem_cache, &init_kmem_cache_node[CACHE_CACHE + nid], nid);
| |----->ptr = kmalloc_node(sizeof(struct kmem_cache_node), GFP_NOWAIT, nodeid);
| | 分配struct kmem_cache_node
| |----->memcpy(ptr, list, sizeof(struct kmem_cache_node));
| | 将静态定义的struct kmem_cache_node拷贝到新分配的struct kmem_cache_node中
| |----->cachep->node[nodeid] = ptr;
|----->init_list(kmalloc_cach