slab子系统初始化的chicken-egg问题(先有鸡还是先有蛋)

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;
        }

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭