slab子系统的初始化,
需要使用kmalloc分配slab系统初始化所需要数据结构的内存,而kmalloc必须在slab系统初始化完成后才能正常工作。
所以这就形成一个环,先有鸡还是先有蛋的问题。
kmem_cache_init()的过程,分以下几步解决这个问题:
1、创建cache_cache和cache_cache中的head array,采用静态数据的方式
2.、使用cache_cache分配第一个通用kmem_cache size = 32, 同时使用静态数据初始化cache的head array
分配后续通用kmem_cache, 从size = 32的cache中分配初始的head array。
3、重新分配的通用cache_cache 中head array
/* 循环初始化所有通用cache */
while (sizes->cs_size) {
/* 第一个kmem_cache创建的时候,g_cpucache_up = NONE */
sizes->cs_cachep = kmem_cache_create(names->name,
sizes->cs_size, ARCH_KMALLOC_MINALIGN,
(ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);
/* Inc off-slab bufctl limit until the ceiling is hit. */
if (!(OFF_SLAB(sizes->cs_cachep))) {
offslab_limit = sizes->cs_size-sizeof(struct slab);
offslab_limit /= sizeof(kmem_bufctl_t);
}
sizes->cs_dmacachep = kmem_cache_create(names->name_dma,
sizes->cs_size, ARCH_KMALLOC_MINALIGN,
(ARCH_KMALLOC_FLAGS | SLAB_CACHE_DMA | SLAB_PANIC),
NULL, NULL);
sizes++;
names++;
}
/* 替换head arrays
{
void * ptr;
ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
local_irq_disable();
BUG_ON(ac_data(&cache_cache) != &initarray_cache.cache);
memcpy(ptr, ac_data(&cache_cache), sizeof(struct arraycache_init));
cache_cache.array[smp_processor_id()] = ptr;
local_irq_enable();
ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
local_irq_disable();
BUG_ON(ac_data(malloc_sizes[0].cs_cachep) != &initarray_generic.cache);
memcpy(ptr, ac_data(malloc_sizes[0].cs_cachep),
sizeof(struct arraycache_init));
malloc_sizes[0].cs_cachep->array[smp_processor_id()] = ptr;
local_irq_enable();
}
/* 调整 通用cache中head arrays 的大小*/
{
kmem_cache_t *cachep;
down(&cache_chain_sem);
list_for_each_entry(cachep, &cache_chain, next)
enable_cpucache(cachep);
up(&cache_chain_sem);
}
/* Done! */
g_cpucache_up = FULL;
在kmem_cache_create()中,
/* 当slab系统初始化完成后,用标准方法初始化cache */
if (g_cpucache_up == FULL) {
enable_cpucache(cachep);
} else {
/* 当状态=none的时候,使用静态结构 */
if (g_cpucache_up == NONE) {
/* Note: the first kmem_cache_create must create
* the cache that's used by kmalloc(24), otherwise
* the creation of further caches will BUG().
*/
cachep->array[cpu] = &initarray_generic.cache;
g_cpucache_up = PARTIAL;
} else {
/* 除size=32以外,其它通用cache的初始化执行这个,kmalloc 将会从size=32的kmem_cache_t中获得内存 */
/* sizeof(struct arraycache_init) 等于 32 */
cachep->array[cpu] = kmalloc(sizeof(struct arraycache_init),GFP_KERNEL);
}
/* 当slab系统没有完全初始化完成时,手动设置percpu中的内容,这些内容会在后续的中覆盖 */
BUG_ON(!ac_data(cachep, cpu));
ac_data(cachep, cpu)->avail = 0;
ac_data(cachep, cpu)->limit = BOOT_CPUCACHE_ENTRIES;
ac_data(cachep, cpu)->batchcount = 1;
ac_data(cachep, cpu)->touched = 0;
cachep->batchcount = 1;
cachep->limit = BOOT_CPUCACHE_ENTRIES;
cachep->free_limit = (1+num_online_cpus())*cachep->batchcount
+ cachep->num;
}