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

Linux Slab分配器(三)--创建缓存

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

创建新的缓存必须通过kmem_cache_create()函数来完成,原型如下

  1. struct kmem_cache *  
  2. kmem_cache_create (const char *name, size_t size, size_t align,  
  3.     unsigned long flags, void (*ctor)(void *))  
  • name:所创建的新缓存的名字
  • size :缓存所分配对象的大小
  • align:对象的对齐值
  • flags:创建用的标识
  • ctor:创建对象时的构造函数

相关阅读:

Linux Slab分配器(一)--概述 http://www.linuxidc.com/Linux/2012-06/62965.htm
Linux Slab分配器(二)--初始化 http://www.linuxidc.com/Linux/2012-06/62966.htm
Linux Slab分配器(三)--创建缓存 http://www.linuxidc.com/Linux/2012-06/63109.htm
Linux Slab分配器(四)--分配对象 http://www.linuxidc.com/Linux/2012-06/63138.htm

kmem_cache_create()的实际工作就是为新的缓存申请缓存描述符,array_cache描述符和kmem_list3描述符,并根据接收的参数对这三个结构中的变量进行相应的初始化。新创建的缓存是空的,不包含slab。

  1. struct kmem_cache *  
  2. kmem_cache_create (const char *name, size_t size, size_t align,  
  3.     unsigned long flags, void (*ctor)(void *))  
  4. {  
  5.     size_t left_over, slab_size, ralign;  
  6.     struct kmem_cache *cachep = NULL, *pc;  
  7.     gfp_t gfp;  
  8.   
  9.     /* 
  10.      * Sanity checks... these are all serious usage bugs. 
  11.      */  
  12.      /*做一些必要的检查,以下情况都是不合法的: 
  13.        1.缓存名为空 
  14.        2.处于中断环境中 
  15.        3.缓存中的对象大小小于处理器的字长 
  16.        4.缓存中的对象大小大于普通缓存的最大长度*/  
  17.     if (!name || in_interrupt() || (size < BYTES_PER_WORD) ||  
  18.         size > KMALLOC_MAX_SIZE) {  
  19.         printk(KERN_ERR "%s: Early error in slab %s\n", __func__,  
  20.                 name);  
  21.         BUG();  
  22.     }  
  23.   
  24.     /* 
  25.      * We use cache_chain_mutex to ensure a consistent view of 
  26.      * cpu_online_mask as well.  Please see cpuup_callback 
  27.      */  
  28.     if (slab_is_available()) {  
  29.         get_online_cpus();  
  30.         mutex_lock(&cache_chain_mutex);  
  31.     }  
  32.   
  33.     list_for_each_entry(pc, &cache_chain, next) {  
  34.         char tmp;  
  35.         int res;  
  36.   
  37.         /* 
  38.          * This happens when the module gets unloaded and doesn't 
  39.          * destroy its slab cache and no-one else reuses the vmalloc 
  40.          * area of the module.  Print a warning. 
  41.          */  
  42.         res = probe_kernel_address(pc->name, tmp);  
  43.         if (res) {  
  44.             printk(KERN_ERR  
  45.                    "SLAB: cache with size %d has lost its name\n",  
  46.                    pc->buffer_size);  
  47.             continue;  
  48.         }  
  49.   
  50.         if (!strcmp(pc->name, name)) {  
  51.             printk(KERN_ERR  
  52.                    "kmem_cache_create: duplicate cache %s\n", name);  
  53.             dump_stack();  
  54.             goto oops;  
  55.         }  
  56.     }  
  57.   
  58. #if DEBUG   
  59.     WARN_ON(strchr(name, ' ')); /* It confuses parsers */  
  60. #if FORCED_DEBUG   
  61.     /* 
  62.      * Enable redzoning and last user accounting, except for caches with 
  63.      * large objects, if the increased size would increase the object size 
  64.      * above the next power of two: caches with object sizes just above a 
  65.      * power of two have a significant amount of internal fragmentation. 
  66.      */  
  67.     if (size < 4096 || fls(size - 1) == fls(size-1 + REDZONE_ALIGN +  
  68.                         2 * sizeof(unsigned long long)))  
  69.         flags |= SLAB_RED_ZONE | SLAB_STORE_USER;  
  70.     if (!(flags & SLAB_DESTROY_BY_RCU))  
  71.         flags |= SLAB_POISON;  
  72. #endif   
  73.     if (flags & SLAB_DESTROY_BY_RCU)  
  74.         BUG_ON(flags & SLAB_POISON);  
  75. #endif   
  76.     /* 
  77.      * Always checks flags, a caller might be expecting debug support which 
  78.      * isn't available. 
  79.      */  
  80.     BUG_ON(flags & ~CREATE_MASK);  
  81.   
  82.     /* 
  83.      * Check that size is in terms of words.  This is needed to avoid 
  84.      * unaligned accesses for some archs when redzoning is used, and makes 
  85.      * sure any on-slab bufctl's are also correctly aligned. 
  86.      */  
  87.      /*如果缓存对象大小没有对齐到处理器字长,则对齐之*/  
  88.     if (size & (BYTES_PER_WORD - 1)) {  
  89.         size += (BYTES_PER_WORD - 1);  
  90.         size &= ~(BYTES_PER_WORD - 1);  
  91.     }  
  92.   
  93.     /* calculate the final buffer alignment: */  
  94.   
  95.     /* 1) arch recommendation: can be overridden for debug */  
  96.     /*要求按照体系结构对齐*/  
  97.     if (flags & SLAB_HWCACHE_ALIGN) {  
  98.         /* 
  99.          * Default alignment: as specified by the arch code.  Except if 
  100.          * an object is really small, then squeeze multiple objects into 
  101.          * one cacheline. 
  102.          */  
  103.         ralign = cache_line_size();/*对齐值取L1缓存行的大小*/  
  104.         /*如果对象大小足够小,则不断压缩对齐值以保证能将足够多的对象装入一个缓存行*/  
  105.         while (size <= ralign / 2)  
  106.             ralign /= 2;  
  107.     } else {  
  108.         ralign = BYTES_PER_WORD; /*对齐值取处理器字长*/  
  109.     }  
  110.   
  111.     /* 
  112.      * Redzoning and user store require word alignment or possibly larger. 
  113.      * Note this will be overridden by architecture or caller mandated 
  114.      * alignment if either is greater than BYTES_PER_WORD. 
  115.      */  
  116.      /*如果开启了DEBUG,则按需要进行相应的对齐*/  
  117.     if (flags & SLAB_STORE_USER)  
  118.         ralign = BYTES_PER_WORD;  
  119.   
  120.     if (flags & SLAB_RED_ZONE) {  
  121.         ralign = REDZONE_ALIGN;  
  122.         /* If redzoning, ensure that the second redzone is suitably 
  123.          * aligned, by adjusting the object size accordingly. */  
  124.         size += REDZONE_ALIGN - 1;  
  125.         size &= ~(REDZONE_ALIGN - 1);  
  126.     }  
  127.   
  128.     /* 2) arch mandated alignment */  
  129.     if (ralign < ARCH_SLAB_MINALIGN) {  
  130.         ralign = ARCH_SLAB_MINALIGN;  
  131.     }  
  132.     /* 3) caller mandated alignment */  
  133.     if (ralign < align) {  
  134.         ralign = align;  
  135.     }  
  136.     /* disable debug if necessary */  
  137.     if (ralign > __alignof__(unsigned long long))  
  138.         flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);  
  139.     /* 
  140.      * 4) Store it. 
  141.      */  
  142.     align = ralign;  
  143.   
  144.     if (slab_is_available())  
  145.         gfp = GFP_KERNEL;  
  146.     else  
  147.         gfp = GFP_NOWAIT;  
  148.   
  149.     /* Get cache's description obj. */  
  150.     /*从cache_cache中分配一个高速缓存描述符*/  
  151.     cachep = kmem_cache_zalloc(&cache_cache, gfp);  
  152.     if (!cachep)  
  153.         goto oops;  
  154.   
  155. #if DEBUG   
  156.     cachep->obj_size = size;  
  157.   
  158.     /* 
  159.      * Both debugging options require word-alignment which is calculated 
  160.      * into align above. 
  161.      */  
  162.     if (flags & SLAB_RED_ZONE) {  
  163.         /* add space for red zone words */  
  164.         cachep->obj_offset += sizeof(unsigned long long);  
  165.         size += 2 * sizeof(unsigned long long);  
  166.     }  
  167.     if (flags & SLAB_STORE_USER) {  
  168.         /* user store requires one word storage behind the end of 
  169.          * the real object. But if the second red zone needs to be 
  170.          * aligned to 64 bits, we must allow that much space. 
  171.          */  
  172.         if (flags & SLAB_RED_ZONE)  
  173.             size += REDZONE_ALIGN;  
  174.         else  
  175.             size += BYTES_PER_WORD;  
  176.     }  
  177. #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)   
  178.     if (size >= malloc_sizes[INDEX_L3 + 1].cs_size  
  179.         && cachep->obj_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) {  
  180.         cachep->obj_offset += PAGE_SIZE - ALIGN(size, align);  
  181.         size = PAGE_SIZE;  
  182.     }  
  183. #endif   
  184. #endif   
  185.   
  186.     /* 
  187.      * Determine if the slab management is 'on' or 'off' slab. 
  188.      * (bootstrapping cannot cope with offslab caches so don't do 
  189.      * it too early on.) 
  190.      */  
  191.      /*如果缓存对象的大小不小于页面大小的1/8并且不处于slab初始化阶段, 
  192.        则选择将slab描述符放在slab外部以腾出更多的空间给对象*/  
  193.     if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init)  
  194.         /* 
  195.          * Size is large, assume best to place the slab management obj 
  196.          * off-slab (should allow better packing of objs). 
  197.          */  
  198.         flags |= CFLGS_OFF_SLAB;  
  199.   
  200.     /*将对象大小按之前确定的align对齐*/  
  201.     size = ALIGN(size, align);  
  202.   
  203.     /*计算slab的对象数,分配给slab的页框阶数并返回slab的剩余空间,即碎片大小*/  
  204.     left_over = calculate_slab_order(cachep, size, align, flags);  
  205.   
  206.     if (!cachep->num) {  
  207.         printk(KERN_ERR  
  208.                "kmem_cache_create: couldn't create cache %s.\n", name);  
  209.         kmem_cache_free(&cache_cache, cachep);  
  210.         cachep = NULL;  
  211.         goto oops;  
  212.     }  
  213.     /*将slab管理区的大小按align进行对齐*/  
  214.     slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)  
  215.               + sizeof(struct slab), align);  
  216.   
  217.     /* 
  218.      * If the slab has been placed off-slab, and we have enough space then 
  219.      * move it on-slab. This is at the expense of any extra colouring. 
  220.      */  
  221.      /*如果之前确定将slab管理区放在slab外部,但是碎片空间大于slab管理区大小, 
  222.        这时改变策略将slab管理区放在slab内部,这样可以节省外部空间,但是会牺牲 
  223.        着色的颜色个数*/  
  224.     if (flags & CFLGS_OFF_SLAB && left_over >= slab_size) {  
  225.         flags &= ~CFLGS_OFF_SLAB;  
  226.         left_over -= slab_size;  
  227.     }  
  228.   
  229.     /*如果的确要将slab管理区放在外部,则不需按照该slab的对齐方式进行对齐了, 
  230.      重新计算slab_size*/  
  231.     if (flags & CFLGS_OFF_SLAB) {  
  232.         /* really off slab. No need for manual alignment */  
  233.         slab_size =  
  234.             cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab);  
  235.   
  236. #ifdef CONFIG_PAGE_POISONING   
  237.         /* If we're going to use the generic kernel_map_pages() 
  238.          * poisoning, then it's going to smash the contents of 
  239.          * the redzone and userword anyhow, so switch them off. 
  240.          */  
  241.         if (size % PAGE_SIZE == 0 && flags & SLAB_POISON)  
  242.             flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);  
  243. #endif   
  244.     }  
  245.   
  246.     /*着色偏移区L1缓存行的大小*/  
  247.     cachep->colour_off = cache_line_size();  
  248.     /* Offset must be a multiple of the alignment. */  
  249.     if (cachep->colour_off < align)/*着色偏移小于align的话则要取对齐值*/  
  250.         cachep->colour_off = align;  
  251.     /*计算着色的颜色数目*/  
  252.     cachep->colour = left_over / cachep->colour_off;  
  253.     cachep->slab_size = slab_size;  
  254.     cachep->flags = flags;  
  255.     cachep->gfpflags = 0;  
  256.     if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA))  
  257.         cachep->gfpflags |= GFP_DMA;  
  258.     cachep->buffer_size = size;  
  259.     cachep->reciprocal_buffer_size = reciprocal_value(size);  
  260.   
  261.     if (flags & CFLGS_OFF_SLAB) {  
  262.         cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);  
  263.         /* 
  264.          * This is a possibility for one of the malloc_sizes caches. 
  265.          * But since we go off slab only for object size greater than 
  266.          * PAGE_SIZE/8, and malloc_sizes gets created in ascending order, 
  267.          * this should not happen at all. 
  268.          * But leave a BUG_ON for some lucky dude. 
  269.          */  
  270.         BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));  
  271.     }  
  272.     cachep->ctor = ctor;  
  273.     cachep->name = name;  
  274.   
  275.     if (setup_cpu_cache(cachep, gfp)) {  
  276.         __kmem_cache_destroy(cachep);  
  277.         cachep = NULL;  
  278.         goto oops;  
  279.     }  
  280.   
  281.     /* cache setup completed, link it into the list */  
  282.     /*将该高速缓存描述符添加进cache_chain*/  
  283.     list_add(&cachep->next, &cache_chain);  
  284. oops:  
  285.     if (!cachep && (flags & SLAB_PANIC))  
  286.         panic("kmem_cache_create(): failed to create slab `%s'\n",  
  287.               name);  
  288.     if (slab_is_available()) {  
  289.         mutex_unlock(&cache_chain_mutex);  
  290.         put_online_cpus();  
  291.     }  
  292.     return cachep;  
  293. }  
linux
相关资讯       Linux内存管理 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

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