【Linux内核思辩】kmallo VS vmalloc,谁与争锋?

kmalloc VS vmalloc

这两个是高频考点,不管在面试过程中,还是在实际项目中,如果涉及到底层Linux内核的开发,都会遇到这个问题。

kmallocmalloc都是Linux内核中的内存分配函数。
但是,二者有什么区别,哪些场景下使用kmalloc,哪些场景下使用vmalloc

先看概念

kmalloc, what is it ?

定义

kmalloc()函数的操作与用户空间的malloc()函数非常相似,不同之处在于多了一个flags参数。kmalloc()函数是获取内核内存的简单接口,以字节为单位分配内存。如果需要整页内存,之前讨论的接口可能是更好的选择。然而,对于大多数内核分配,kmalloc()是首选的接口。

函数在<linux/slab.h>中声明如下:

void * kmalloc(size_t size, int flags)

该函数返回一个指向至少size字节长度的内存区域的指针。分配的内存区域是物理连续的。出错时,它返回NULL。内核分配总是成功的,除非可用内存不足。因此,在所有调用kmalloc()后,必须检查NULL并适当处理错误。

它可能会分配比请求的更多,尽管无法知道多少更多!因为内核分配器的核心是基于页面的,所以一些分配可能会四舍五入以适应可用内存。内核永远不会返回比请求的内存少。如果内核无法找到至少所需的内存量,分配失败,函数返回NULL。

我们来看一个例子。假设您需要为一个虚构的dog结构动态分配足够的空间:

struct dog *ptr;

ptr = kmalloc(sizeof(struct dog), GFP_KERNEL);
if (!ptr)
/* 处理错误... */

如果kmalloc()调用成功,ptr现在指向一个至少为请求大小的内存块。GFP_KERNEL标志指定了在尝试获取返回给kmalloc()调用者的内存时内存分配器的行为。

注意事项

在实际使用过程中,使用kmalloc()函数时要注意内存泄漏,如果分配了内存但没有正确释放,会导致内核内存的浪费。在内核中释放由kmalloc()分配的内存,需要使用kfree()函数。例如:

kfree(ptr);

释放内存后,建议将指针设置为NULL,以避免悬挂指针:

ptr = NULL;

这样可以确保在以后使用这个指针时,不会引用已经释放的内存。在内核编程中,内存管理非常重要,确保正确分配和释放内存对于系统稳定性至关重要。

先看看函数的原型和实现

/**
 * kmalloc - allocate kernel memory
 * @size: how many bytes of memory are required.
 * @flags: describe the allocation context
 *
 * kmalloc is the normal method of allocating memory
 * for objects smaller than page size in the kernel.
 *
 * The allocated object address is aligned to at least ARCH_KMALLOC_MINALIGN
 * bytes. For @size of power of two bytes, the alignment is also guaranteed
 * to be at least to the size.
 *
 * The @flags argument may be one of the GFP flags defined at
 * include/linux/gfp.h and described at
 * :ref:`Documentation/core-api/mm-api.rst <mm-api-gfp-flags>`
 *
 * The recommended usage of the @flags is described at
 * :ref:`Documentation/core-api/memory-allocation.rst <memory_allocation>`
 *
 * Below is a brief outline of the most useful GFP flags
 *
 * %GFP_KERNEL
 *	Allocate normal kernel ram. May sleep.
 *
 * %GFP_NOWAIT
 *	Allocation will not sleep.
 *
 * %GFP_ATOMIC
 *	Allocation will not sleep.  May use emergency pools.
 *
 * Also it is possible to set different flags by OR'ing
 * in one or more of the following additional @flags:
 *
 * %__GFP_ZERO
 *	Zero the allocated memory before returning. Also see kzalloc().
 *
 * %__GFP_HIGH
 *	This allocation has high priority and may use emergency pools.
 *
 * %__GFP_NOFAIL
 *	Indicate that this allocation is in no way allowed to fail
 *	(think twice before using).
 *
 * %__GFP_NORETRY
 *	If memory is not immediately available,
 *	then give up at once.
 *
 * %__GFP_NOWARN
 *	If allocation fails, don't issue any warnings.
 *
 * %__GFP_RETRY_MAYFAIL
 *	Try really hard to succeed the allocation but fail
 *	eventually.
 */
#ifndef CONFIG_SLOB
static __always_inline __alloc_size(1) void *kmalloc(size_t size, gfp_t flags)
{
	if (__builtin_constant_p(size) && size) {
		unsigned int index;

		if (size > KMALLOC_MAX_CACHE_SIZE)
			return kmalloc_large(size, flags);

		index = kmalloc_index(size);
		return kmalloc_trace(
				kmalloc_caches[kmalloc_type(flags)][index],
				flags, size);
	}
	return __kmalloc(size, flags);
}
#else
static __always_inline __alloc_size(1) void *kmalloc(size_t size, gfp_t flags)
{
	if (__builtin_constant_p(size) && size > KMALLOC_MAX_CACHE_SIZE)
		return kmalloc_large(size, flags);

	return __kmalloc(size, flags);
}
#endif

未完待续。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值