kmalloc函數的核心機制就是slab函數
static __always_inline void *kmalloc(size_t size, gfp_t flags) { if (__builtin_constant_p(size)) { #ifndef CONFIG_SLOB unsigned int index; #endif if (size > KMALLOC_MAX_CACHE_SIZE) return kmalloc_large(size, flags); #ifndef CONFIG_SLOB //查找是哪一個slab緩衝區 index = kmalloc_index(size); if (!index) return ZERO_SIZE_PTR; return kmem_cache_alloc_trace( kmalloc_caches[kmalloc_type(flags)][index], flags, size); #endif } return __kmalloc(size, flags); }
若是申請大小超過kmalloc的最大值,就會調用kmalloc_large函數,會直接向野蠻分配器申請內存。ui
static __always_inline void *kmalloc_large(size_t size, gfp_t flags) { unsigned int order = get_order(size); return kmalloc_order_trace(size, flags, order); } void *kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order) { void *ret = kmalloc_order(size, flags, order); trace_kmalloc(_RET_IP_, ret, size, PAGE_SIZE << order, flags); return ret; } /* 爲了不沒必要要的開銷,咱們將大量分配請求直接傳遞給頁面分配器。咱們使用__GFP_COMP,由於咱們將須要知道分配順序以正確釋放kfree中的頁面。 */ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order) { void *ret; struct page *page; flags |= __GFP_COMP; page = alloc_pages(flags, order); ret = page ? page_address(page) : NULL; kmemleak_alloc(ret, size, 1, flags); kasan_kmalloc_large(ret, size, flags); return ret; }
不然調用kmalloc_index函數,查找可用的slab緩衝區code
static __always_inline void *kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t flags, size_t size) { void *ret = kmem_cache_alloc(s, flags); kasan_kmalloc(s, ret, size, flags); return ret; }
找到kmem_cache描述符以後,調用kmem_cache_alloc函數申請內存。對象
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) { void *ret = slab_alloc(cachep, flags, _RET_IP_); trace_kmem_cache_alloc(_RET_IP_, ret, cachep->object_size, cachep->size, flags); return ret; }
這裏就回到了前面的申請slab對象的流程中了。內存