手机版
你好,游客 登录 注册 搜索
背景:
阅读新闻

Linux Slab分配器(二)--初始化

[日期:2012-06-15] 来源:Linux社区  作者:vanbreaker [字体: ]

cache_cache的初始化和普通高速缓存的建立由start_kernel()-->mm_init()-->kmem_cache_init()函数来完成,下面就来看具体的初始化代码

  1. void __init kmem_cache_init(void)  
  2. {  
  3.     size_t left_over;  
  4.     struct cache_sizes *sizes;  
  5.     struct cache_names *names;  
  6.     int i;  
  7.     int order;  
  8.     int node;  
  9.   
  10.     if (num_possible_nodes() == 1)  
  11.         use_alien_caches = 0;  
  12.   
  13.     /*初始化静态L3变量initkmem_list3*/  
  14.     for (i = 0; i < NUM_INIT_LISTS; i++) {  
  15.         kmem_list3_init(&initkmem_list3[i]);  
  16.         if (i < MAX_NUMNODES)  
  17.             cache_cache.nodelists[i] = NULL;  
  18.     }  
  19.     /*将cache_cache和initkmem_list3相关联*/  
  20.     set_up_list3s(&cache_cache, CACHE_CACHE);  
  21.   
  22.     /* 
  23.      * Fragmentation resistance on low memory - only use bigger 
  24.      * page orders on machines with more than 32MB of memory. 
  25.      */  
  26.     if (totalram_pages > (32 << 20) >> PAGE_SHIFT)  
  27.         slab_break_gfp_order = BREAK_GFP_ORDER_HI;  
  28.   
  29.     /* Bootstrap is tricky, because several objects are allocated 
  30.      * from caches that do not exist yet: 
  31.      * 1) initialize the cache_cache cache: it contains the struct 
  32.      *    kmem_cache structures of all caches, except cache_cache itself: 
  33.      *    cache_cache is statically allocated. 
  34.      *    Initially an __init data area is used for the head array and the 
  35.      *    kmem_list3 structures, it's replaced with a kmalloc allocated 
  36.      *    array at the end of the bootstrap. 
  37.      * 2) Create the first kmalloc cache. 
  38.      *    The struct kmem_cache for the new cache is allocated normally. 
  39.      *    An __init data area is used for the head array. 
  40.      * 3) Create the remaining kmalloc caches, with minimally sized 
  41.      *    head arrays. 
  42.      * 4) Replace the __init data head arrays for cache_cache and the first 
  43.      *    kmalloc cache with kmalloc allocated arrays. 
  44.      * 5) Replace the __init data for kmem_list3 for cache_cache and 
  45.      *    the other cache's with kmalloc allocated memory. 
  46.      * 6) Resize the head arrays of the kmalloc caches to their final sizes. 
  47.      */  
  48.   
  49.     node = numa_node_id();  
  50.   
  51.     /*初始化cache_cache的其余部分*/  
  52.   
  53.     /* 1) create the cache_cache */  
  54.     INIT_LIST_HEAD(&cache_chain);  
  55.     list_add(&cache_cache.next, &cache_chain);  
  56.     cache_cache.colour_off = cache_line_size();  
  57.     cache_cache.array[smp_processor_id()] = &initarray_cache.cache;  
  58.     cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node];  
  59.   
  60.     /* 
  61.      * struct kmem_cache size depends on nr_node_ids, which 
  62.      * can be less than MAX_NUMNODES. 
  63.      */  
  64.     cache_cache.buffer_size = offsetof(struct kmem_cache, nodelists) +  
  65.                  nr_node_ids * sizeof(struct kmem_list3 *);  
  66. #if DEBUG   
  67.     cache_cache.obj_size = cache_cache.buffer_size;  
  68. #endif   
  69.     cache_cache.buffer_size = ALIGN(cache_cache.buffer_size,  
  70.                     cache_line_size());  
  71.     cache_cache.reciprocal_buffer_size =  
  72.         reciprocal_value(cache_cache.buffer_size);  
  73.   
  74.     /*计算cache_cache的剩余空间以及slab中对象的数目,order决定了slab的大小(PAGE_SIZE<<order)*/  
  75.     for (order = 0; order < MAX_ORDER; order++) {  
  76.         cache_estimate(order, cache_cache.buffer_size,  
  77.             cache_line_size(), 0, &left_over, &cache_cache.num);  
  78.         /*当该order计算出来的num,即slab中对象的数目不为0时,则跳出循环*/  
  79.         if (cache_cache.num)  
  80.             break;  
  81.     }  
  82.     BUG_ON(!cache_cache.num);  
  83.     cache_cache.gfporder = order;/*确定分配给每个slab的页数的对数*/  
  84.     cache_cache.colour = left_over / cache_cache.colour_off;/*确定可用颜色的数目*/  
  85.     /*确定slab管理区的大小,即slab描述符以及kmem_bufctl_t数组*/  
  86.     cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +  
  87.                       sizeof(struct slab), cache_line_size());  
  88.   
  89.     /* 2+3) create the kmalloc caches */  
  90.     sizes = malloc_sizes;  
  91.     names = cache_names;  
  92.   
  93.     /* 
  94.      * Initialize the caches that provide memory for the array cache and the 
  95.      * kmem_list3 structures first.  Without this, further allocations will 
  96.      * bug. 
  97.      */  
  98.     /*为了后面能够调用kmalloc()创建per-CPU高速缓存和kmem_list3高速缓存, 
  99.        这里必须先创建大小相应的general cache*/  
  100.     sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name,  
  101.                     sizes[INDEX_AC].cs_size,  
  102.                     ARCH_KMALLOC_MINALIGN,  
  103.                     ARCH_KMALLOC_FLAGS|SLAB_PANIC,  
  104.                     NULL);  
  105.   
  106.     /*如果AC和L3在malloc_sizes中的偏移不一样,也就是说它们的大小不属于同一级别, 
  107.      则创建AC的gerneral cache,否则两者共用一个gerneral cache*/  
  108.     if (INDEX_AC != INDEX_L3) {  
  109.         sizes[INDEX_L3].cs_cachep =  
  110.             kmem_cache_create(names[INDEX_L3].name,  
  111.                 sizes[INDEX_L3].cs_size,  
  112.                 ARCH_KMALLOC_MINALIGN,  
  113.                 ARCH_KMALLOC_FLAGS|SLAB_PANIC,  
  114.                 NULL);  
  115.     }  
  116.   
  117.     slab_early_init = 0;  
  118.   
  119.     /*创建各级的gerneral cache*/  
  120.     while (sizes->cs_size != ULONG_MAX) {  
  121.         /* 
  122.          * For performance, all the general caches are L1 aligned. 
  123.          * This should be particularly beneficial on SMP boxes, as it 
  124.          * eliminates "false sharing". 
  125.          * Note for systems short on memory removing the alignment will 
  126.          * allow tighter packing of the smaller caches. 
  127.          */  
  128.         if (!sizes->cs_cachep) {  
  129.             sizes->cs_cachep = kmem_cache_create(names->name,  
  130.                     sizes->cs_size,  
  131.                     ARCH_KMALLOC_MINALIGN,  
  132.                     ARCH_KMALLOC_FLAGS|SLAB_PANIC,  
  133.                     NULL);  
  134.         }  
  135. #ifdef CONFIG_ZONE_DMA   
  136.         sizes->cs_dmacachep = kmem_cache_create(  
  137.                     names->name_dma,  
  138.                     sizes->cs_size,  
  139.                     ARCH_KMALLOC_MINALIGN,  
  140.                     ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA|  
  141.                         SLAB_PANIC,  
  142.                     NULL);  
  143. #endif   
  144.         sizes++;  
  145.         names++;  
  146.     }  
  147.     /* 4) Replace the bootstrap head arrays */  
  148.     {  
  149.         struct array_cache *ptr;  
  150.   
  151.         /*这里调用kmalloc()为cache_cache创建per-CPU高速缓存*/  
  152.         ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);  
  153.   
  154.         BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);  
  155.         /*将静态定义的initarray_cache中的array_cache拷贝到malloc申请到的空间中*/  
  156.         memcpy(ptr, cpu_cache_get(&cache_cache),  
  157.                sizeof(struct arraycache_init));  
  158.         /* 
  159.          * Do not assume that spinlocks can be initialized via memcpy: 
  160.          */  
  161.         spin_lock_init(&ptr->lock);  
  162.   
  163.         /*将cache_cache与保存per-CPU高速缓存的空间关联*/  
  164.         cache_cache.array[smp_processor_id()] = ptr;  
  165.   
  166.         /*为之前创建的AC gerneral cache创建per-CPU高速缓存,替换静态定义的initarray_generic.cache*/  
  167.         ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);  
  168.   
  169.         BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep)  
  170.                != &initarray_generic.cache);  
  171.         memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),  
  172.                sizeof(struct arraycache_init));  
  173.         /* 
  174.          * Do not assume that spinlocks can be initialized via memcpy: 
  175.          */  
  176.         spin_lock_init(&ptr->lock);  
  177.   
  178.         malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =  
  179.             ptr;  
  180.     }  
  181.     /* 5) Replace the bootstrap kmem_list3's */  
  182.     {  
  183.         int nid;  
  184.   
  185.         for_each_online_node(nid) {  
  186.               
  187.             /*为cache_cache的kmem_list3申请高速缓存空间,并替换静态定义的initkmem_list3*/  
  188.             init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid);  
  189.   
  190.             /*为AC的kmem_list3申请高速缓存空间,并替换静态定义的initkmem_list3*/  
  191.             init_list(malloc_sizes[INDEX_AC].cs_cachep,  
  192.                   &initkmem_list3[SIZE_AC + nid], nid);  
  193.   
  194.             if (INDEX_AC != INDEX_L3) {  
  195.             /*为L3的kmem_list3申请高速缓存空间,并替换静态定义的initkmem_list3*/  
  196.                 init_list(malloc_sizes[INDEX_L3].cs_cachep,  
  197.                       &initkmem_list3[SIZE_L3 + nid], nid);  
  198.             }  
  199.         }  
  200.     }  
  201.   
  202.     g_cpucache_up = EARLY;  
  203. }  
linux
相关资讯       Linux内存管理 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款