免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1553 | 回复: 1
打印 上一主题 下一主题

Linux内存管理之slab机制(初始化)2.。。。。。。。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-01-10 10:32 |只看该作者 |倒序浏览
Linux内存管理之slab机制(初始化)2.。。。。。。。
  1. #ifdef CONFIG_ZONE_DMA
  2.                 sizes->cs_dmacachep = kmem_cache_create(
  3.                                         names->name_dma,
  4.                                         sizes->cs_size,
  5.                                         ARCH_KMALLOC_MINALIGN,
  6.                                         ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA|
  7.                                                 SLAB_PANIC,
  8.                                         NULL);
  9. #endif
  10.                 sizes++;
  11.                 names++;
  12.         }
  13.         /* 至此,kmalloc general cache已经创建完毕,可以拿来使用了 */
  14.         /* 4) Replace the bootstrap head arrays */
  15.         /* 第四步,用kmalloc对象替换静态分配的全局变量
  16.         。到目前为止一共使用了两个全局local cache
  17.         ,一个是cache_cache的local cache指向initarray_cache.cache
  18.         ,另一个是malloc_sizes[INDEX_AC].cs_cachep的local cache指向initarray_generic.cache
  19.         ,参见setup_cpu_cache函数。这里替换它们。*/
  20.         {
  21.                 struct array_cache *ptr;
  22.                 /* 申请cache_cache所用local cache的空间 */
  23.                 ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);

  24.                 BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);
  25.                 /* 复制原cache_cache的local cache,即initarray_cache,到新的位置 */
  26.                 memcpy(ptr, cpu_cache_get(&cache_cache),
  27.                        sizeof(struct arraycache_init));
  28.                 /*
  29.                  * Do not assume that spinlocks can be initialized via memcpy:
  30.                  */
  31.                 spin_lock_init(&ptr->lock);
  32.                 /* cache_cache的local cache指向新的位置 */
  33.                 cache_cache.array[smp_processor_id()] = ptr;
  34.                 /* 申请malloc_sizes[INDEX_AC].cs_cachep所用local cache的空间 */
  35.                 ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);

  36.                 BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep)
  37.                        != &initarray_generic.cache);
  38.                 /* 复制原local cache到新分配的位置,注意此时local cache的大小是固定的 */
  39.                 memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),
  40.                        sizeof(struct arraycache_init));
  41.                 /*
  42.                  * Do not assume that spinlocks can be initialized via memcpy:
  43.                  */
  44.                 spin_lock_init(&ptr->lock);

  45.                 malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
  46.                     ptr;
  47.         }
  48.         /* 5) Replace the bootstrap kmem_list3's */
  49.         /* 第五步,与第四步类似,用kmalloc的空间替换静态分配的slab三链 */
  50.         {
  51.                 int nid;
  52.           /* UMA只有一个节点 */
  53.                 for_each_online_node(nid) {
  54.                         /* 复制struct kmem_cache的slab三链 */
  55.                         init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
  56.                         /* 复制struct arraycache_init的slab三链 */
  57.                         init_list(malloc_sizes[INDEX_AC].cs_cachep,
  58.                                   &initkmem_list3[SIZE_AC + nid], nid);
  59.                         /* 复制struct kmem_list3的slab三链 */
  60.                         if (INDEX_AC != INDEX_L3) {
  61.                                 init_list(malloc_sizes[INDEX_L3].cs_cachep,
  62.                                           &initkmem_list3[SIZE_L3 + nid], nid);
  63.                         }
  64.                 }
  65.         }
  66.         /* 更新slab系统初始化进度 */
  67.         g_cpucache_up = EARLY;
  68. }
复制代码
]辅助操作

1,slab三链初始化
  1. view plaincopy to clipboardprint?static void kmem_list3_init(struct kmem_list3 *parent)  
  2. {  
  3.     INIT_LIST_HEAD(&parent->slabs_full);  
  4.     INIT_LIST_HEAD(&parent->slabs_partial);  
  5.     INIT_LIST_HEAD(&parent->slabs_free);  
  6.     parent->shared = NULL;  
  7.     parent->alien = NULL;  
  8.     parent->colour_next = 0;  
  9.     spin_lock_init(&parent->list_lock);  
  10.     parent->free_objects = 0;  
  11.     parent->free_touched = 0;  
  12. }  
  13. static void kmem_list3_init(struct kmem_list3 *parent)
  14. {
  15.         INIT_LIST_HEAD(&parent->slabs_full);
  16.         INIT_LIST_HEAD(&parent->slabs_partial);
  17.         INIT_LIST_HEAD(&parent->slabs_free);
  18.         parent->shared = NULL;
  19.         parent->alien = NULL;
  20.         parent->colour_next = 0;
  21.         spin_lock_init(&parent->list_lock);
  22.         parent->free_objects = 0;
  23.         parent->free_touched = 0;
  24. }
复制代码
2,slab三链静态数据初始化
  1. view plaincopy to clipboardprint? /*设置cache的slab三链指向静态分配的全局变量*/  
  2. static void __init set_up_list3s(struct kmem_cache *cachep, int index)  
  3. {  
  4.     int node;  
  5.     /* UMA只有一个节点 */  
  6.     for_each_online_node(node) {  
  7.         /* 全局变量initkmem_list3是初始化阶段使用的slab三链 */  
  8.         cachep->nodelists[node] = &initkmem_list3[index + node];  
  9.         /* 设置回收时间 */  
  10.         cachep->nodelists[node]->next_reap = jiffies +  
  11.             REAPTIMEOUT_LIST3 +  
  12.             ((unsigned long)cachep) % REAPTIMEOUT_LIST3;  
  13.     }  
  14. }  
  15. /*设置cache的slab三链指向静态分配的全局变量*/
  16. static void __init set_up_list3s(struct kmem_cache *cachep, int index)
  17. {
  18.         int node;
  19.         /* UMA只有一个节点 */
  20.         for_each_online_node(node) {
  21.                 /* 全局变量initkmem_list3是初始化阶段使用的slab三链 */
  22.                 cachep->nodelists[node] = &initkmem_list3[index + node];
  23.                 /* 设置回收时间 */
  24.                 cachep->nodelists[node]->next_reap = jiffies +
  25.                     REAPTIMEOUT_LIST3 +
  26.                     ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
  27.         }
  28. }
复制代码
3,计算每个slab中对象的数目

view plaincopy to clipboardprint?/*
  1. * Calculate the number of objects and left-over bytes for a given buffer size.
  2. */  
  3. /*计算每个slab中对象的数目。*/  
  4. /*
  5. 1)        gfporder:slab由2gfporder个页面组成。
  6. 2)        buffer_size:对象的大小。
  7. 3)        align:对象的对齐方式。
  8. 4)        flags:内置式slab还是外置式slab。
  9. 5)        left_over:slab中浪费空间的大小。
  10. 6)        num:slab中的对象数目。
  11. */  
  12. static void cache_estimate(unsigned long gfporder, size_t buffer_size,  
  13.                size_t align, int flags, size_t *left_over,  
  14.                unsigned int *num)  
  15. {  
  16.     int nr_objs;  
  17.     size_t mgmt_size;  
  18.     /* slab大小为1<<order个页面 */  
  19.     size_t slab_size = PAGE_SIZE << gfporder;  
  20.   
  21.     /*
  22.      * The slab management structure can be either off the slab or
  23.      * on it. For the latter case, the memory allocated for a
  24.      * slab is used for:
  25.      *
  26.      * - The struct slab
  27.      * - One kmem_bufctl_t for each object
  28.      * - Padding to respect alignment of @align
  29.      * - @buffer_size bytes for each object
  30.      *
  31.      * If the slab management structure is off the slab, then the
  32.      * alignment will already be calculated into the size. Because
  33.      * the slabs are all pages aligned, the objects will be at the
  34.      * correct alignment when allocated.
  35.      */  
  36.     if (flags & CFLGS_OFF_SLAB) {  
  37.         /* 外置式slab */  
  38.         mgmt_size = 0;  
  39.         /* slab页面不含slab管理对象,全部用来存储slab对象 */  
  40.         nr_objs = slab_size / buffer_size;  
  41.         /* 对象数不能超过上限 */  
  42.         if (nr_objs > SLAB_LIMIT)  
  43.             nr_objs = SLAB_LIMIT;  
  44.     } else {  
  45.         /*
  46.          * Ignore padding for the initial guess. The padding
  47.          * is at most @align-1 bytes, and @buffer_size is at
  48.          * least @align. In the worst case, this result will
  49.          * be one greater than the number of objects that fit
  50.          * into the memory allocation when taking the padding
  51.          * into account.
  52.          *//* 内置式slab,slab管理对象与slab对象在一起
  53.          ,此时slab页面中包含:一个struct slab对象,一个kmem_bufctl_t数组,slab对象。
  54.          kmem_bufctl_t数组大小与slab对象数目相同 */  
  55.         nr_objs = (slab_size - sizeof(struct slab)) /  
  56.               (buffer_size + sizeof(kmem_bufctl_t));  
  57.   
  58.         /*
  59.          * This calculated number will be either the right
  60.          * amount, or one greater than what we want.
  61.          *//* 计算cache line对齐后的大小,如果超出了slab总的大小,则对象数减一 */  
  62.         if (slab_mgmt_size(nr_objs, align) + nr_objs*buffer_size  
  63.                > slab_size)  
  64.             nr_objs--;  
  65.   
  66.         if (nr_objs > SLAB_LIMIT)  
  67.             nr_objs = SLAB_LIMIT;  
  68.         /* 计算cache line对齐后slab管理对象的大小 */  
  69.         mgmt_size = slab_mgmt_size(nr_objs, align);  
  70.     }  
  71.     *num = nr_objs;/* 保存slab对象数目 */  
  72.     /* 计算浪费空间的大小 */  
  73.     *left_over = slab_size - nr_objs*buffer_size - mgmt_size;  
  74. }  
  75. /*
  76. * Calculate the number of objects and left-over bytes for a given buffer size.
  77. */
  78. /*计算每个slab中对象的数目。*/
  79. /*
  80. 1)        gfporder:slab由2gfporder个页面组成。
  81. 2)        buffer_size:对象的大小。
  82. 3)        align:对象的对齐方式。
  83. 4)        flags:内置式slab还是外置式slab。
  84. 5)        left_over:slab中浪费空间的大小。
  85. 6)        num:slab中的对象数目。
  86. */
  87. static void cache_estimate(unsigned long gfporder, size_t buffer_size,
  88.                            size_t align, int flags, size_t *left_over,
  89.                            unsigned int *num)
  90. {
  91.         int nr_objs;
  92.         size_t mgmt_size;
  93.         /* slab大小为1<<order个页面 */
  94.         size_t slab_size = PAGE_SIZE << gfporder;

  95.         /*
  96.          * The slab management structure can be either off the slab or
  97.          * on it. For the latter case, the memory allocated for a
  98.          * slab is used for:
  99.          *
  100.          * - The struct slab
  101.          * - One kmem_bufctl_t for each object
  102.          * - Padding to respect alignment of @align
  103.          * - @buffer_size bytes for each object
  104.          *
  105.          * If the slab management structure is off the slab, then the
  106.          * alignment will already be calculated into the size. Because
  107.          * the slabs are all pages aligned, the objects will be at the
  108.          * correct alignment when allocated.
  109.          */
  110.         if (flags & CFLGS_OFF_SLAB) {
  111.                 /* 外置式slab */
  112.                 mgmt_size = 0;
  113.                 /* slab页面不含slab管理对象,全部用来存储slab对象 */
  114.                 nr_objs = slab_size / buffer_size;
  115.                 /* 对象数不能超过上限 */
  116.                 if (nr_objs > SLAB_LIMIT)
  117.                         nr_objs = SLAB_LIMIT;
  118.         } else {
  119.                 /*
  120.                  * Ignore padding for the initial guess. The padding
  121.                  * is at most @align-1 bytes, and @buffer_size is at
  122.                  * least @align. In the worst case, this result will
  123.                  * be one greater than the number of objects that fit
  124.                  * into the memory allocation when taking the padding
  125.                  * into account.
  126.                  *//* 内置式slab,slab管理对象与slab对象在一起
  127.                  ,此时slab页面中包含:一个struct slab对象,一个kmem_bufctl_t数组,slab对象。
  128.                  kmem_bufctl_t数组大小与slab对象数目相同 */
  129.                 nr_objs = (slab_size - sizeof(struct slab)) /
  130.                           (buffer_size + sizeof(kmem_bufctl_t));

  131.                 /*
  132.                  * This calculated number will be either the right
  133.                  * amount, or one greater than what we want.
  134.                  *//* 计算cache line对齐后的大小,如果超出了slab总的大小,则对象数减一 */
  135.                 if (slab_mgmt_size(nr_objs, align) + nr_objs*buffer_size
  136.                        > slab_size)
  137.                         nr_objs--;

  138.                 if (nr_objs > SLAB_LIMIT)
  139.                         nr_objs = SLAB_LIMIT;
  140.                 /* 计算cache line对齐后slab管理对象的大小 */
  141.                 mgmt_size = slab_mgmt_size(nr_objs, align);
  142.         }
  143.         *num = nr_objs;/* 保存slab对象数目 */
  144.         /* 计算浪费空间的大小 */
  145.         *left_over = slab_size - nr_objs*buffer_size - mgmt_size;
  146. }
复制代码
辅助数据结构与变量

Linux内核中将所有的通用cache以不同的大小存放在数组中,以方便查找。其中malloc_sizes[]数组为cache_sizes类型的数组,存放各个cache的大小;cache_names[]数组为cache_names结构类型数组,存放各个cache大小的名称;malloc_sizes[]数组和cache_names[]数组下标对应,也就是说cache_names名称的cache对应的大小为malloc_sizes
  1. view plaincopy to clipboardprint?/* Size description struct for general caches. */  
  2. struct cache_sizes {  
  3.     size_t          cs_size;  
  4.     struct kmem_cache   *cs_cachep;  
  5. #ifdef CONFIG_ZONE_DMA   
  6.     struct kmem_cache   *cs_dmacachep;  
  7. #endif   
  8. };  
  9. /*
  10. * These are the default caches for kmalloc. Custom caches can have other sizes.
  11. */  
  12. struct cache_sizes malloc_sizes[] = {  
  13. #define CACHE(x) { .cs_size = (x) },   
  14. #include <linux/kmalloc_sizes.h>   
  15.     CACHE(ULONG_MAX)  
  16. #undef CACHE   
  17. };  
  18. /* Size description struct for general caches. */
  19. struct cache_sizes {
  20.         size_t                         cs_size;
  21.         struct kmem_cache        *cs_cachep;
  22. #ifdef CONFIG_ZONE_DMA
  23.         struct kmem_cache        *cs_dmacachep;
  24. #endif
  25. };
  26. /*
  27. * These are the default caches for kmalloc. Custom caches can have other sizes.
  28. */
  29. struct cache_sizes malloc_sizes[] = {
  30. #define CACHE(x) { .cs_size = (x) },
  31. #include <linux/kmalloc_sizes.h>
  32.         CACHE(ULONG_MAX)
  33. #undef CACHE
  34. };view plaincopy to clipboardprint?/* Must match cache_sizes above. Out of line to keep cache footprint low. */  
  35. struct cache_names {  
  36.     char *name;  
  37.     char *name_dma;  
  38. };  
  39.   
  40. static struct cache_names __initdata cache_names[] = {  
  41. #define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" },   
  42. #include <linux/kmalloc_sizes.h>   
  43.     {NULL,}  
  44. #undef CACHE   
  45. };  
  46. /* Must match cache_sizes above. Out of line to keep cache footprint low. */
  47. struct cache_names {
  48.         char *name;
  49.         char *name_dma;
  50. };

  51. static struct cache_names __initdata cache_names[] = {
  52. #define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" },
  53. #include <linux/kmalloc_sizes.h>
  54.         {NULL,}
  55. #undef CACHE
  56. };
复制代码
二、内核启动末期初始化

1,根据对象大小计算local cache中对象数目上限;

2,借助数据结构ccupdate_struct操作cpu本地cache。为每个在线cpu分配cpu本地cache;

3,用新分配的cpu本地cache替换原有的cache;

4,更新slab三链以及cpu本地共享cache。

论坛徽章:
0
2 [报告]
发表于 2012-01-10 10:32 |只看该作者
谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP