slab之kmalloc

内核版本: 2.6.11

1. 高速缓存类型

高速缓存分为两种类型:普通和专用。

普通高速缓存由slab分配器用于自己的目的,而专用缓存则有内核其他部分创建使用。

专用高速缓存由kmem_cache_create()函数创建,创建一个专用高速缓存,这个缓存中object大小是固定的。

2. 使用场景

专用高速缓存:频繁使用固定大小内存,创建一个指定大小的cache,然后在这个cache中申请和释放object。

普通高速缓存:偶尔使用某个大小的object,单独创建个cache则显得浪费,内核提供了普通高速缓存。

3. 普通高速缓存实现

3.1 malloc_sizes

 506 /* These are the default caches for kmalloc. Custom caches can have other sizes. */
 507 struct cache_sizes malloc_sizes[] = {                                           
 508 #define CACHE(x) { .cs_size = (x) },                                            
 509 #include <linux/kmalloc_sizes.h>                                                
 510         { 0, }                                                                  
 511 #undef CACHE                                                                    
 512 }; 

这个数组包含了一系列通用大小的cache,大小为2^5, 2^6…33554432大小obj的缓存。

malloc_sizes包含一个头文件kmalloc_sizes.h,内容如下:

  1 #if (PAGE_SIZE == 4096)                                                         
  2         CACHE(32)                                                               
  3 #endif                                                                          
  4         CACHE(64)                                                                                                                                                                                             
  5 #if L1_CACHE_BYTES < 64                                                         
  6         CACHE(96)                                                               
  7 #endif                                                                          
  8         CACHE(128)                                                              
  9 #if L1_CACHE_BYTES < 128                                                        
 10         CACHE(192)                                                              
 11 #endif                                                                          
 12         CACHE(256)                                                              
 13         CACHE(512)                                                              
 14         CACHE(1024)                                                             
 15         CACHE(2048)                                                             
 16         CACHE(4096)                                                             
 17         CACHE(8192)                                                             
 18         CACHE(16384)                                                            
 19         CACHE(32768)                                                            
 20         CACHE(65536)                                                            
 21         CACHE(131072)                                                           
 22 #ifndef CONFIG_MMU                                                              
 23         CACHE(262144)                                                           
 24         CACHE(524288)                                                           
 25         CACHE(1048576)                                                          
 26 #ifdef CONFIG_LARGE_ALLOCS                                                      
 27         CACHE(2097152)                                                          
 28         CACHE(4194304)                                                          
 29         CACHE(8388608)                                                          
 30         CACHE(16777216)                                                         
 31         CACHE(33554432)                                                         
 32 #endif /* CONFIG_LARGE_ALLOCS */                                                
 33 #endif /* CONFIG_MMU */          

结构体cache_sizes定义如下:

 76 /* Size description struct for general caches. */                               
 77 struct cache_sizes {                                                                                                                                                                                          
 78         size_t           cs_size;                                               
 79         kmem_cache_t    *cs_cachep;                                             
 80         kmem_cache_t    *cs_dmacachep;                                          
 81 };

说明:
cs_size 指定了这一项中cache的object大小。每一项都包含两个cache,一个提供用于DMA操作的内存,一个提供用于正常操作的内存。

3.2 创建malloc_sizes指定cache

普通缓存的创建在kmem_cache_init中完成。

 744 void __init kmem_cache_init(void)                                               
 745 {                                                                               
 746         size_t left_over;                                                       
 747         struct cache_sizes *sizes;                                              
 748         struct cache_names *names;
 ...
  793         /* 2+3) create the kmalloc caches */                                    
 794         sizes = malloc_sizes;                                                   
 795         names = cache_names;                                                    
 796                                                                                 
 797         while (sizes->cs_size) {                                                
 798                 /* For performance, all the general caches are L1 aligned.      
 799                  * This should be particularly beneficial on SMP boxes, as it   
 800                  * eliminates "false sharing".                                  
 801                  * Note for systems short on memory removing the alignment will 
 802                  * allow tighter packing of the smaller caches. */              
 803                 sizes->cs_cachep = kmem_cache_create(names->name,               
 804                         sizes->cs_size, ARCH_KMALLOC_MINALIGN,                  
 805                         (ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);         
 806                                                                                 
 807                 /* Inc off-slab bufctl limit until the ceiling is hit. */       
 808                 if (!(OFF_SLAB(sizes->cs_cachep))) {                            
 809                         offslab_limit = sizes->cs_size-sizeof(struct slab);     
 810                         offslab_limit /= sizeof(kmem_bufctl_t);                 
 811                 }                                                               
 812                                                                                 
 813                 sizes->cs_dmacachep = kmem_cache_create(names->name_dma,        
 814                         sizes->cs_size, ARCH_KMALLOC_MINALIGN,                  
 815                         (ARCH_KMALLOC_FLAGS | SLAB_CACHE_DMA | SLAB_PANIC),     
 816                         NULL, NULL);                                            
 817                                                                                 
 818                 sizes++;                                                        
 819                 names++;                                                        
 820         }   
 ......

在794到820行通过函数kmem_cache_create创建,大小为32,64,…,33554432大小的cache。
普通缓存,也是通过kmem_cache_create创建。

普通缓存的API

普通缓存kmalloc的定义如下:

 85 static inline void *kmalloc(size_t size, int flags)                             
 86 {                                                                               
 87         if (__builtin_constant_p(size)) {                                       
 88                 int i = 0;                                                      
 89 #define CACHE(x) \                                                              
 90                 if (size <= x) \                                                
 91                         goto found; \                                           
 92                 else \                                                          
 93                         i++;                                                    
 94 #include "kmalloc_sizes.h"                                                      
 95 #undef CACHE                                                                    
 96                 {                                                               
 97                         extern void __you_cannot_kmalloc_that_much(void);       
 98                         __you_cannot_kmalloc_that_much();                       
 99                 }                                                               
100 found:                                                                          
101                 return kmem_cache_alloc((flags & GFP_DMA) ?                     
102                         malloc_sizes[i].cs_dmacachep :                          
103                         malloc_sizes[i].cs_cachep, flags);                      
104         }                                                                       
105         return __kmalloc(size, flags);                                          
106 } 

在87行中,如果是常量进入这个函数,重新定义CACHE(x),在kmalloc_size.h,有CACHE(32),CACHE(64),…,CACHE(33554432),分别执行90-93行,找到后,到found这个tag中,然后通过kmem_cache_alloc从之前创建的general cache中创建了object,并返回这个object。
如果不是常量,进入105行。

函数__kmalloc的定义如下:

2454 void * __kmalloc (size_t size, int flags)                                                                                                                                                                    
2455 {                                                                               
2456         struct cache_sizes *csizep = malloc_sizes;                              
2457                                                                                 
2458         for (; csizep->cs_size; csizep++) {                                     
2459                 if (size > csizep->cs_size)                                     
2460                         continue;                                               
2461 #if DEBUG                                                                       
2462                 /* This happens if someone tries to call                        
2463                  * kmem_cache_create(), or kmalloc(), before                    
2464                  * the generic caches are initialized.                          
2465                  */                                                             
2466                 BUG_ON(csizep->cs_cachep == NULL);                              
2467 #endif                                                                          
2468                 return __cache_alloc(flags & GFP_DMA ?                          
2469                          csizep->cs_dmacachep : csizep->cs_cachep, flags);      
2470         }                                                                       
2471         return NULL;                                                            
2472 }    

找到和需要分配的size最接近的缓存,进入 函数 __cache_alloc从这个缓存( csizep->cs_cachep或者csizep->cs_dmacachep)分配到object。

2135 static inline void * __cache_alloc (kmem_cache_t *cachep, int flags)            
2136 {                                                                               
2137         unsigned long save_flags;                                               
2138         void* objp;                                                             
2139         struct array_cache *ac;                                                 
2140                                                                                 
2141         cache_alloc_debugcheck_before(cachep, flags);                           
2142                                                                                 
2143         local_irq_save(save_flags);                                             
2144         ac = ac_data(cachep);                                                   
2145         if (likely(ac->avail)) {                                                
2146                 STATS_INC_ALLOCHIT(cachep);                                     
2147                 ac->touched = 1;                                                
2148                 objp = ac_entry(ac)[--ac->avail];                               
2149         } else {                                                                
2150                 STATS_INC_ALLOCMISS(cachep);                                    
2151                 objp = cache_alloc_refill(cachep, flags);                       
2152         }                                                                       
2153         local_irq_restore(save_flags);                                          
2154         objp = cache_alloc_debugcheck_after(cachep, flags, objp, __builtin_return_address(0));   
// 分配后调试检查
2155         return objp;                                                            
2156 }  

通过cache_alloc_debugcheck_after从缓存cachep分配到object

参考

深入理解linux内核
Kernel那些事儿之内存管理(9) — Slab(下)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值