歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> Linux教程

Linux內存管理之slab機制(創建cache)

Linux內核中創建cache節點由函數kmem_cache_create()實現。

該函數的執行流程:

1,從全局cache_cache中獲得cache結構,因為全局cache_cache初始化對象的大小就是kmem_cache結構的大小,所以返回的指針正好可以轉換為cache結構;調用 kmem_cache_zalloc(&cache_cache, gfp);

2,獲得slab中碎片大小,由函數calculate_slab_order()實現;

3,計算並初始化cache的各種屬性,如果是外置式,需要用kmem_find_general_cachep(slab_size, 0u)指定cachep->slabp_cache,用於存放slab對象和kmem_bufctl_t[]數組;

4,設置每個CPU上得本地cache,setup_cpu_cache();

5,cache創建完畢,將其加入到全局slab cache鏈表中;

一、主實現

[cpp]
  1. /** 
  2.  * kmem_cache_create - Create a cache. 
  3.  * @name: A string which is used in /proc/slabinfo to identify this cache. 
  4.  * @size: The size of objects to be created in this cache. 
  5.  * @align: The required alignment for the objects. 
  6.  * @flags: SLAB flags 
  7.  * @ctor: A constructor for the objects. 
  8.  * 
  9.  * Returns a ptr to the cache on success, NULL on failure. 
  10.  * Cannot be called within a int, but can be interrupted. 
  11.  * The @ctor is run when new pages are allocated by the cache. 
  12.  * 
  13.  * @name must be valid until the cache is destroyed. This implies that 
  14.  * the module calling this has to destroy the cache before getting unloaded. 
  15.  * Note that kmem_cache_name() is not guaranteed to return the same pointer, 
  16.  * therefore applications must manage it themselves. 
  17.  * 
  18.  * The flags are 
  19.  * 
  20.  * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) 
  21.  * to catch references to uninitialised memory. 
  22.  * 
  23.  * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check 
  24.  * for buffer overruns. 
  25.  * 
  26.  * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware 
  27.  * cacheline.  This can be beneficial if you're counting cycles as closely 
  28.  * as davem. 
  29.  */  
  30.  /*創建slab系統頂層的cache節點。創建完成後,cache 
  31.  裡並沒有任何slab以及對象,只有當分配對象 
  32.  ,並且cache中沒有空閒對象時,才會創建新的slab。*/  
  33. struct kmem_cache *  
  34. kmem_cache_create (const char *name, size_t size, size_t align,  
  35.     unsigned long flags, void (*ctor)(void *))  
  36. {  
  37.     size_t left_over, slab_size, ralign;  
  38.     struct kmem_cache *cachep = NULL, *pc;  
  39.     gfp_t gfp;  
  40.   
  41.     /* 
  42.      * Sanity checks... these are all serious usage bugs. 
  43.      *//* 安全性檢查 */  
  44.     if (!name || in_interrupt() || (size < BYTES_PER_WORD) ||  
  45.         size > KMALLOC_MAX_SIZE) {  
  46.         printk(KERN_ERR "%s: Early error in slab %s\n", __func__,  
  47.                 name);  
  48.         BUG();  
  49.     }  
  50.   
  51.     /* 
  52.      * We use cache_chain_mutex to ensure a consistent view of 
  53.      * cpu_online_mask as well.  Please see cpuup_callback 
  54.      */  
  55.      /* slab分配器是否已經初始化好,如果是內核啟動階段 
  56.      ,則只有一個cpu執行slab分配器的初始化動作,無需加鎖,否則需要加鎖 */  
  57.     if (slab_is_available()) {  
  58.         get_online_cpus();  
  59.         mutex_lock(&cache_chain_mutex);  
  60.     }  
  61.     /* 遍歷cache鏈,做些校驗工作 */  
  62.     list_for_each_entry(pc, &cache_chain, next) {  
  63.         char tmp;  
  64.         int res;  
  65.   
  66.         /* 
  67.          * This happens when the module gets unloaded and doesn't 
  68.          * destroy its slab cache and no-one else reuses the vmalloc 
  69.          * area of the module.  Print a warning. 
  70.          */  
  71.         /* 檢查cache鏈表中的cache是否都有名字 */  
  72.         res = probe_kernel_address(pc->name, tmp);  
  73.         if (res) {/*沒有名字,報錯*/  
  74.             printk(KERN_ERR  
  75.                    "SLAB: cache with size %d has lost its name\n",  
  76.                    pc->buffer_size);  
  77.             continue;  
  78.         }  
  79.          /* 檢查cache鏈表中是否已經存在相同名字的cache */  
  80.         if (!strcmp(pc->name, name)) {  
  81.             printk(KERN_ERR  
  82.                    "kmem_cache_create: duplicate cache %s\n", name);  
  83.             dump_stack();  
  84.             goto oops;  
  85.         }  
  86.     }  
  87.   
  88. #if DEBUG   
  89.     WARN_ON(strchr(name, ' ')); /* It confuses parsers */  
  90. #if FORCED_DEBUG   
  91.     /* 
  92.      * Enable redzoning and last user accounting, except for caches with 
  93.      * large objects, if the increased size would increase the object size 
  94.      * above the next power of two: caches with object sizes just above a 
  95.      * power of two have a significant amount of internal fragmentation. 
  96.      */  
  97.     if (size < 4096 || fls(size - 1) == fls(size-1 + REDZONE_ALIGN +  
  98.                         2 * sizeof(unsigned long long)))  
  99.         flags |= SLAB_RED_ZONE | SLAB_STORE_USER;  
  100.     if (!(flags & SLAB_DESTROY_BY_RCU))  
  101.         flags |= SLAB_POISON;  
  102. #endif   
  103.     if (flags & SLAB_DESTROY_BY_RCU)  
  104.         BUG_ON(flags & SLAB_POISON);  
  105. #endif   
  106.     /* 
  107.      * Always checks flags, a caller might be expecting debug support which 
  108.      * isn't available. 
  109.      */  
  110.     BUG_ON(flags & ~CREATE_MASK);  
  111.   
  112.     /* 
  113.      * Check that size is in terms of words.  This is needed to avoid 
  114.      * unaligned accesses for some archs when redzoning is used, and makes 
  115.      * sure any on-slab bufctl's are also correctly aligned. 
  116.      */  
  117.     if (size & (BYTES_PER_WORD - 1)) {  
  118.         size += (BYTES_PER_WORD - 1);  
  119.         size &= ~(BYTES_PER_WORD - 1);  
  120.     }  
  121.   
  122.     /* calculate the final buffer alignment: */  
  123.   
  124.     /* 1) arch recommendation: can be overridden for debug */  
  125.     if (flags & SLAB_HWCACHE_ALIGN) {  
  126.         /* 
  127.          * Default alignment: as specified by the arch code.  Except if 
  128.          * an object is really small, then squeeze multiple objects into 
  129.          * one cacheline. 
  130.          */  
  131.         ralign = cache_line_size();  
  132.         while (size <= ralign / 2)  
  133.             ralign /= 2;  
  134.     } else {  
  135.         ralign = BYTES_PER_WORD;  
  136.     }  
  137.   
  138.     /* 
  139.      * Redzoning and user store require word alignment or possibly larger. 
  140.      * Note this will be overridden by architecture or caller mandated 
  141.      * alignment if either is greater than BYTES_PER_WORD. 
  142.      */  
  143.     if (flags & SLAB_STORE_USER)  
  144.         ralign = BYTES_PER_WORD;  
  145.   
  146.     if (flags & SLAB_RED_ZONE) {  
  147.         ralign = REDZONE_ALIGN;  
  148.         /* If redzoning, ensure that the second redzone is suitably 
  149.          * aligned, by adjusting the object size accordingly. */  
  150.         size += REDZONE_ALIGN - 1;  
  151.         size &= ~(REDZONE_ALIGN - 1);  
  152.     }  
  153.   
  154.     /* 2) arch mandated alignment */  
  155.     if (ralign < ARCH_SLAB_MINALIGN) {  
  156.         ralign = ARCH_SLAB_MINALIGN;  
  157.     }  
  158.     /* 3) caller mandated alignment */  
  159.     if (ralign < align) {  
  160.         ralign = align;  
  161.     }  
  162.     /* disable debug if necessary */  
  163.     if (ralign > __alignof__(unsigned long long))  
  164.         flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);  
  165.     /* 
  166.      * 4) Store it. 
  167.      */  
  168.     align = ralign;  
  169.     /* slab分配器是否已經可用 */  
  170.     if (slab_is_available())  
  171.         gfp = GFP_KERNEL;  
  172.     else  
  173.         /* slab初始化好之前,不允許阻塞,且只能在低端內存區分配 */  
  174.         gfp = GFP_NOWAIT;  
  175.   
  176.     /* Get cache's description obj. */  
  177.     /* 獲得struct kmem_cache對象 ,為什麼能從cache中獲得的對象是 
  178.     kmem_cache結構呢,因為這裡的全局變量cache_cache的對象大小 
  179.     就是kmem_cache結構大小*/  
  180.     cachep = kmem_cache_zalloc(&cache_cache, gfp);  
  181.     if (!cachep)  
  182.         goto oops;  
  183.   
  184. #if DEBUG   
  185.     cachep->obj_size = size;  
  186.   
  187.     /* 
  188.      * Both debugging options require word-alignment which is calculated 
  189.      * into align above. 
  190.      */  
  191.     if (flags & SLAB_RED_ZONE) {  
  192.         /* add space for red zone words */  
  193.         cachep->obj_offset += sizeof(unsigned long long);  
  194.         size += 2 * sizeof(unsigned long long);  
  195.     }  
  196.     if (flags & SLAB_STORE_USER) {  
  197.         /* user store requires one word storage behind the end of 
  198.          * the real object. But if the second red zone needs to be 
  199.          * aligned to 64 bits, we must allow that much space. 
  200.          */  
  201.         if (flags & SLAB_RED_ZONE)  
  202.             size += REDZONE_ALIGN;  
  203.         else  
  204.             size += BYTES_PER_WORD;  
  205.     }  
  206. #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)   
  207.     if (size >= malloc_sizes[INDEX_L3 + 1].cs_size  
  208.         && cachep->obj_size > cache_line_size() && size < PAGE_SIZE) {  
  209.         cachep->obj_offset += PAGE_SIZE - size;  
  210.         size = PAGE_SIZE;  
  211.     }  
  212. #endif   
  213. #endif   
  214.   
  215.     /* 
  216.      * Determine if the slab management is 'on' or 'off' slab. 
  217.      * (bootstrapping cannot cope with offslab caches so don't do 
  218.      * it too early on.) 
  219.      */  
  220.      /* 確定slab管理對象的存儲方式:內置還是外置 
  221.      。通常,當對象大於等於512時,使用外置方式 
  222.      。初始化階段采用內置式。 
  223.      slab_early_init 參見kmem_cache_init函數 */  
  224.     if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init)  
  225.         /* 
  226.          * Size is large, assume best to place the slab management obj 
  227.          * off-slab (should allow better packing of objs). 
  228.          */  
  229.         flags |= CFLGS_OFF_SLAB;  
  230.   
  231.     size = ALIGN(size, align);  
  232.     /* 獲得slab中碎片的大小 */  
  233.     left_over = calculate_slab_order(cachep, size, align, flags);  
  234.     /* cachep->num為該cache中每個slab的對象數,為0,表示為該對象創建cache失敗 */  
  235.     if (!cachep->num) {  
  236.         printk(KERN_ERR  
  237.                "kmem_cache_create: couldn't create cache %s.\n", name);  
  238.         kmem_cache_free(&cache_cache, cachep);  
  239.         cachep = NULL;  
  240.         goto oops;  
  241.     }  
  242.     /* 計算slab管理對象的大小,包括struct slab對象和kmem_bufctl_t數組 */  
  243.     slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)  
  244.               + sizeof(struct slab), align);  
  245.   
  246.     /* 
  247.      * If the slab has been placed off-slab, and we have enough space then 
  248.      * move it on-slab. This is at the expense of any extra colouring. 
  249.      */  
  250.   
  251.     /* 如果這是一個外置式slab,並且碎片大小大於slab管理對象的大小 
  252.     ,則可將slab管理對象移到slab中,改造成一個內置式slab */  
  253.     if (flags & CFLGS_OFF_SLAB && left_over >= slab_size) {  
  254.         /* 除去off-slab標志位 */  
  255.         flags &= ~CFLGS_OFF_SLAB;  
  256.         /* 更新碎片大小 */  
  257.         left_over -= slab_size;  
  258.     }  
  259.   
  260.     if (flags & CFLGS_OFF_SLAB) {  
  261.         /* really off slab. No need for manual alignment */  
  262.         /* align是針對slab對象的,如果slab管理對象是外置存儲 
  263.         ,自然不會像內置那樣影響到後面slab對象的存儲位置 
  264.         ,也就不需要對齊了 */  
  265.         slab_size =  
  266.             cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab);  
  267.   
  268. #ifdef CONFIG_PAGE_POISONING   
  269.         /* If we're going to use the generic kernel_map_pages() 
  270.          * poisoning, then it's going to smash the contents of 
  271.          * the redzone and userword anyhow, so switch them off. 
  272.          */  
  273.         if (size % PAGE_SIZE == 0 && flags & SLAB_POISON)  
  274.             flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);  
  275. #endif   
  276.     }  
  277.     /* cache的著色塊的單位大小 */  
  278.     cachep->colour_off = cache_line_size();  
  279.     /* Offset must be a multiple of the alignment. */  
  280.     /* 著色塊大小必須是對象要求對齊方式的倍數 */  
  281.     if (cachep->colour_off < align)  
  282.         cachep->colour_off = align;  
  283.      /* 計算碎片區需要多少個著色快 */  
  284.     cachep->colour = left_over / cachep->colour_off;  
  285.      /* slab管理對象的大小 */  
  286.     cachep->slab_size = slab_size;  
  287.     cachep->flags = flags;  
  288.     cachep->gfpflags = 0;  
  289.     if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA))  
  290.         cachep->gfpflags |= GFP_DMA;  
  291.     /* slab對象的大小 */  
  292.     cachep->buffer_size = size;  
  293.      /* 計算對象在slab中索引時用,參見obj_to_index函數 */  
  294.     cachep->reciprocal_buffer_size = reciprocal_value(size);  
  295.   
  296.     if (flags & CFLGS_OFF_SLAB) {  
  297.         /* 分配一個slab管理區域對象,保存在slabp_cache中, 
  298.         這個函數傳入的大小為slab_size,也就是分配slab_size大小的cache 
  299.         ,在slab創建的時候如果是外置式,那麼需要從分配的這裡面 
  300.         分配出slab對象,剩下的空間放kmem_bufctl_t[]數組, 
  301.         如果是內置式的slab,此指針為空 */  
  302.         cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);  
  303.         /* 
  304.          * This is a possibility for one of the malloc_sizes caches. 
  305.          * But since we go off slab only for object size greater than 
  306.          * PAGE_SIZE/8, and malloc_sizes gets created in ascending order, 
  307.          * this should not happen at all. 
  308.          * But leave a BUG_ON for some lucky dude. 
  309.          */  
  310.         BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));  
  311.     }  
  312.     cachep->ctor = ctor;  
  313.     cachep->name = name;  
  314.     /* 設置每個cpu上的local cache */  
  315.     if (setup_cpu_cache(cachep, gfp)) {  
  316.         __kmem_cache_destroy(cachep);  
  317.         cachep = NULL;  
  318.         goto oops;  
  319.     }  
  320.   
  321.     /* cache setup completed, link it into the list */  
  322.     /* cache創建完畢,將其加入到全局slab cache鏈表中 */  
  323.     list_add(&cachep->next, &cache_chain);  
  324. oops:  
  325.     if (!cachep && (flags & SLAB_PANIC))  
  326.         panic("kmem_cache_create(): failed to create slab `%s'\n",  
  327.               name);  
  328.     if (slab_is_available()) {  
  329.         mutex_unlock(&cache_chain_mutex);  
  330.         put_online_cpus();  
  331.     }  
  332.     return cachep;  
  333. }  

其中,cache_cache

[cpp]
  1. /* internal cache of cache description objs */  
  2. static struct kmem_cache cache_cache = {  
  3.     .batchcount = 1,  
  4.     .limit = BOOT_CPUCACHE_ENTRIES,  
  5.     .shared = 1,  
  6.     .buffer_size = sizeof(struct kmem_cache),/*大小為cache結構,難怪名稱為cache_cache*/  
  7.     .name = "kmem_cache",  
  8. };  
Copyright © Linux教程網 All Rights Reserved