【Linux内核思辩】kmallo VS vmalloc,谁与争锋?
kmalloc VS vmalloc
这两个是高频考点,不管在面试过程中,还是在实际项目中,如果涉及到底层Linux内核的开发,都会遇到这个问题。
kmalloc和malloc都是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
未完待续。。。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
