25.kmalloc的简单描述
kmalloc的实现
kmalloc的基础是一个数组,其中是一些分别用于不同内存长度的slab缓存。数组项是cache_sizes的实例,该数据结构定义如下:
<slab_def.h> struct cache_sizes { size_t cs_size; kmem_cache_t *cs_cachep; kmem_cache_t *cs_dmacachep; #ifdef CONFIG_ZONE_DMA struct kmem_cache *cs_dmacachep; #endif }
cs_size指定了该项负责的内存区的长度。每个长度对应于两个slab缓存,其中之一提供适合DMA访问的内存。
静态定义的malloc_sizes数组包括了所有可用的长度,基本上都是2的幂次,介乎25 =32和225=33 554 432之间,最大值依赖于KMALLOC_MAX_SIZE的设置。
mm/slab.c static struct cache_sizes malloc_sizes[] = { #define CACHE(x) { .cs_size = (x) }, #if (PAGE_SIZE == 4096) CACHE(32) #endif CACHE(64) #if L1_CACHE_BYTES < 64 CACHE(96) #endif CACHE(128) #if L1_CACHE_BYTES < 128 CACHE(192) #endif CACHE(256) CACHE(512) CACHE(1024) CACHE(2048) CACHE(4096) CACHE(8192) CACHE(16384) CACHE(32768) CACHE(65536) CACHE(131072) #if KMALLOC_MAX_SIZE >= 262144 CACHE(262144) #endif #if KMALLOC_MAX_SIZE >= 524288 CACHE(524288) #endif ... #if KMALLOC_MAX_SIZE >= 33554432 CACHE(33554432) CACHE(ULONG_MAX)
指向对应缓存的指针没有初始值。在kmem_cache_init进行初始化时,同时会对这些指针赋值。
kmalloc定义在<slab_def.h>,该函数首先检查是否用常数来指定所需分配内存的长度。在这种情况下,所需的缓存可以在编译时静态确定,这可以提高速度。否则,该函数调用__kmalloc查找长度匹配的缓存。后者是__do_kmalloc的前端,提供参数转换功能。
mm/slab.c void *__do_kmalloc(size_t size, gfp_t flags) { kmem_cache_t *cachep; cachep = __find_general_cachep(size, flags); if (unlikely(ZERO_OR_NULL_PTR(cachep))) return NULL; return __cache_alloc(cachep, flags); }
在__find_general_cachep找到适当的缓存后(遍历所有可能的kmalloc长度,找到一个匹配的缓存),主要的工作则委托给上文讨论过的__cache_alloc函数完成。
kfree的实现
mm/slab.c void kfree(const void *objp) { kmem_cache_t *c; unsigned long flags; if (unlikely(ZERO_OR_NULL_PTR(objp))) return; c = virt_to_cache(objp)); __cache_free(c, (void*)objp); }
在找到与内存指针关联的缓存之后,kfree将实际工作移交上文讨论过的__cache_free函数完成。
__cache_alloc参见23.slab分配器(分配对象kmem_cache_alloc和缓存的增长cache_grow)
__cache_free参见24.slab分配器(释放对象kmem_cache_free,销毁缓存kmem_cache_destroy)