Linux内核内存分配函数之kmalloc

Linux内核内存分配函数之kmalloc,第1张

本文介绍Linux内核内存分配函数 kmalloc 。

注:

1) __builtin_constant_p 编译器内联函数,判断传入参数是否为常量。如果是变量,直接调用 __kmalloc 函数。

2) KMALLOC_MAX_CACHE_SIZE 表示系统创建 slab cache 的最大值为8K,定义如下:

RockPI 4A Linux内核使能 ARM64_4K_PAGES 。可使用命令 getconf 查看 page size ,具体如下:

3) kmalloc 一般用于小内存分配,RockPI 4A Linux内核基于 slub ( CONFIG_SLUB=y )实现。系统先用页分配器分配以页为最小单位的连续物理地址,然后 kmalloc 在此基础上根据调用者的需要进行切分。如果分配超过 KMALLOC_MAX_CACHE_SIZE ,则使用 kmalloc_large 进行大内存分配,即调用页分配器分配内存。( 后续仔细学习

4) kmalloc 分配的内存在物理上连续,可用于DMA设备。 vmalloc 分配的内存是线性地址连续,物理地址不连续,不可用于DMA设备。

size :分配内存的大小,以字节为单位;

flags :分配内存的类型,包括:

1) GFP_USER :可能会引起休眠,用于为用户空间分配内存。

2) GFP_KERNEL :可能会引起休眠,用于内核内存正常分配。

3) GFP_ATOMIC :不会引起休眠,可用于中断处理程序中内存分配。

4) GFP_HIGHUSER :从高端内存中分配内存。

5) GFP_DMA :用于DMA内存分配。

6)其它类型见: include/linux/gfp.h

GFP 可理解为 get free page 。

返回分配内存的首地址,是虚拟地址(线性地址)。

正所谓有借有还,再借不难。每次 kmalloc ,都要有对应的内存释放函数 kfree 。定义文件: mm/slub.c ,如下:

Linux内核空间中常见的内存分配函数

void *kmalloc(size_t size,gfp_t flags) kmalloc() 申请的内存位于物理内存映射区域,而且在物理上也是连续的,它们与真实的物理地址只有一个固定的偏移,因为存在较简单的转换关系,所以对申请的内存大小有限制,不能超过128KB。

较常用的flags()有:

flags 的参考用法:

 |– 进程上下文,可以睡眠 GFP_KERNEL

 |– 进程上下文,不可以睡眠GFP_ATOMIC

 ||– 中断处理程序 GFP_ATOMIC

 ||– 软中断GFP_ATOMIC

 ||– Tasklet GFP_ATOMIC

 |– 用于DMA的内存,可以睡眠 GFP_DMA | GFP_KERNEL

 |– 用于DMA的内存,不可以睡眠GFP_DMA |GFP_ATOMIC

释放内存

void kfree(const void *objp)

kzalloc() 函数与 kmalloc() 非常相似,参数及返回值是一样的,可以说是前者是后者的一个变种,因为 kzalloc() 实际上只是额外附加了 __GFP_ZERO 标志。所以它除了申请内核内存外,还会对申请到的内存内容清零。 kzalloc() 对应的内存释放函数也是 kfree()。

static inline void *kzalloc(size_t size,gfp_t flags) {return kmalloc(size,flags |_GFP_ZERO)}

void *vmalloc(unsigned long size)vmalloc() 函数则会在虚拟内存空间给出一块连续的内存区,但这片连续的虚拟内存在物理内存中并不一定连续。由于 vmalloc() 没有保证申请到的是连续的物理内存,因此对申请的内存大小没有限制,如果需要申请较大的内存空间就需要用此函数了。

释放内存

void vfree(const void *addr)

注意vmalloc和vfree时可以睡眠的,因此不能从中断上下问调用

kmalloc()、kzalloc()、vmalloc() 的区别是:

一般地,在使用虚拟内存技术的多任务系统上,内核和应用有不同的地址空间,因此,在内核和应用之间以及在应用与应用之间进行数据交换需要专门的机制来实现,众所周知,进程间通信(IPC)机制就是为实现应用与应用之间的数据交换而专门实现的。

通常情况下,应用程序通过内核接口访问驱动程序,因此,驱动程序需要和应用程序交换数据。Linux将存储器分为“内核空间”和“用户空间”。 *** 作系统和驱动程序在内核空间运行,应用程序在用户空间运行,两者不能简单地使用指针传递数据。因为Linux系统使用了虚拟内存机制,用户空间的内存可能被换出,当内核空间使用用户空间指针时,对应的数据可能不在内存中。Linux内核提供了多个函数和宏用于内核空间和用户空间传递数据。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7303398.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-04
下一篇 2023-04-04

发表评论

登录后才能评论

评论列表(0条)

保存