【內核源碼學習筆記】slab分配器(6)kmalloc函數

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對象的流程中了。內存

相關文章
相關標籤/搜索