【Linux】内核空间动态内存申请

在这里插入图片描述

🔥博客主页:PannLZ

😘欢迎关注:👍点赞🙌收藏✍️留言


内核空间动态内存申请

1.kmalloc()

#include <linux/slab.h>

void *kmalloc(size_t size, int flags);

参数:

  1. 分配的块的大小
  2. 分配标志,用于控制kmalloc的行为。

最常用的分配标志是GFP_KERNEL,其含义是在内核空间的进程中申请内存。kmalloc()的底层依赖于 __get_free_pages()来实现,分配标志的前缀GFP正 好是这个底层函数的缩写。使用GFP_KERNEL标志申请 内存时,若暂时不能满足,则进程会睡眠等待页,即 会引起阻塞,因此不能在中断上下文或持有自旋锁的 时候使用GFP_KERNE申请内存。

其他一些申请标志:

GFP_USER用来为用户空 间页分配内存,可能阻塞
GFP_HIGHUSER类似 GFP_USER,但是它从高端内存分配
GFP_DMA从 DMA区域分配内存
GFP_NOIO不允许任何I/O初始 化
GFP_NOFS不允许进行任何文件系统调用
__GFP_HIGHMEM指示分配的内存可以位于高端内 存
__GFP_COLD请求一个较长时间不访问的 页
__GFP_NOWARN当一个分配无法满足时,阻止 内核发出警告
__GFP_HIGH高优先级请求,允许 获得被内核保留给紧急状况使用的最后的内存页
__GFP_REPEAT分配失败,则尽力重复尝试
__GFP_NOFAIL标志只许申请成功,不推荐
__GFP_NORETRY若申请不到,则立即放弃

kzalloc()

kzalloc()函数在本质上就是 kmalloc() 函数,只不过多了一个自动帮我们把所申请到的内存清零的操作而已。

kcalloc()

kcalloc()函数的本质也是 kmalloc() 函数。它相较于 kzalloc() 函数又多了一层“数量”的封装。

/**
 * kcalloc - allocate memory for an array. The memory is set to zero.
 * @n: number of elements.
 * @size: element size.
 * @flags: the type of memory to allocate (see kmalloc).
 */
static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
{
    return kmalloc_array(n, size, flags | __GFP_ZERO);
}
static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
{
    if (size != 0 && n > SIZE_MAX / size)
        return NULL;
    return __kmalloc(n * size, flags);
}

使用上面三个函数申请的内存都应使用kfree()释 放,这个函数的用法和用户空间的free()类似

2._ _get_free_pages()

_ _get_free_pages()系列函数/宏是 kmalloc()实现的基础,_ _get_free_pages()系列函数/宏包括 get_zeroed_page()__get_free_page()_ _get_free_pages()

get_zeroed_page(unsigned int flags); //该函数返回一个指向新页的指针并且将该页清零。
__get_free_page(unsigned int flags); 
//该宏返回一个指向新页的指针但是该页不清零,它实际上为:
#define __get_free_page(gfp_mask) \
__get_free_pages((gfp_mask),0)  
//就是调用了下面的__get_free_pages()申请1页。

__get_free_pages(unsigned int flags, unsigned int order); 
/*该函数可分配多个页并返回分配内存的首地址,分配的页数为 2^order,分配的页也不清零。order 允许的最大值是 10(即 1024 页)或者 11(即2048 页),依赖于具体的硬件平台。*/

__get_free_pages()和get_zeroed_page()在 实现中调用了alloc_pages()函数, alloc_pages()既可以在内核空间分配,也可以在用 户空间分配,其原型为:

struct page * alloc_pages(int gfp_mask, unsigned long order);
/*参数含义与__get_free_pages()类似,但它返
回分配的第一个页的描述符而非首地址。*/

使用_ _get_free_pages()系列函数/宏申请的内存应使用下列函数释放:

void free_page(unsigned long addr);
void free_pages(unsigned long addr, unsigned long order);

__get_free_pages等函数在使用时,其申请标志 的值与kmalloc()完全一样,各标志的含义也与 kmalloc()完全一致,最常用的是GFP_KERNELGFP_ATOMIC

3.vmalloc()

vmalloc()一般用在为只存在于软件中(没有对应的硬件意义,因为分配的内存区域在物理内存中可能是分散的,而不是一个连续的物理内存块)的较大的顺序缓冲区分配内存,开销远大于__get_free_pages(),为了完成 vmalloc(),新的页表需要被建立。因此,只是调用 vmalloc()来分配少量的内存(如 1 页)是不妥的。
vmalloc()申请的内存应使用 vfree()释放,vmalloc()和 vfree()的函数原型如下:

void *vmalloc(unsigned long size);
void vfree(void * addr);

vmalloc()不能用在原子上下文中,因为它的内 部实现使用了标志为GFP_KERNELkmalloc()

使用vmalloc()函数的一个例子函数是 create_module()系统调用,它利用vmalloc()函 数来获取被创建模块需要的内存空间。

vmalloc()在申请内存时,会进行内存的映射, 改变页表项,不像kmalloc()实际用的是开机过程中 就映射好的DMA和常规区域的页表项。因此 vmalloc()的虚拟地址和物理地址不是一个简单的线 性映射。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值