【内核源码学习笔记】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对象的流程中了。内存

相关文章
相关标签/搜索