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

kmalloc VS vmalloc

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

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

先看概念

kmalloc, what is it ?

定义

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

函数在中声明如下:

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 `** The recommended usage of the @flags is described at* :ref:`Documentation/core-api/memory-allocation.rst `** 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

未完待续。。。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部