注:
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系统用户空间中动态申请内存的函数为malloc (),这个函数在各种 *** 作系统上的使用都是一致的,malloc ()申请的内存的释放函数为free()。对于Linux而言,C库的malloc ()函数一般通过brk ()和mmap ()两个系统调用从内核申请内存。由于用户空间C库的malloc算法实际上具备一个二次管理能力,所以并不是每次申请和释放内存都一定伴随着对内核的系统调用。比如,代码清单11.2的应用程序可以从内核拿到内存后,立即调用free(),由于free()之前调用了mallopt(M_TRIM_THRESHOLD,一1)和mallopt (M_MMAP_MAX,0),这个free ()并不会把内存还给内核,而只是还给了C库的分配算法(内存仍然属于这个进程),因此之后所有的动态内存申请和释放都在用户态下进行。另外,Linux内核总是采用按需调页(Demand Paging),因此当malloc ()返回的时候,虽然是成功返回,但是内核并没有真正给这个进程内存,这个时候如果去读申请的内存,内容全部是0,这个页面的映射是只读的。只有当写到某个页面的时候,内核才在页错误后,真正把这个页面给这个进程。在Linux内核空间中申请内存涉及的函数主要包括kmalloc( ) 、get free pages ( )和vmalloc ()等。kmalloc ()和_get_free pages ()(及其类似函数)申请的内存位于DMA和常规区域的映射区,而且在物理上也是连续的,它们与真实的物理地址只有一个固定的偏移,因此存在较简单的转换关系。而vmalloc()在虚拟内存空间给出一块连续的内存区,实质上,这片连续的虚拟内存在物理内存中并不一定连续,而vmalloc ()申请的虚拟内存和物理内存之间也没有简单的换算关系。欢迎分享,转载请注明来源:内存溢出
评论列表(0条)