目录
一、CAM的必要性
二、当应用层申请大的内存时的解决方法
三、CAM使用方法
1、内核配置:
2、 配置CMA区域有3种方法
3、设备树源码解析
四、技术原理
1、创建CMA区域
2、把CAM区域释放给页分配器
3、从CMA区域借用页
4、从CMA区域分配内存
5、释放CMA区域的内存
系统长时间运行后,可能碎片化,很难找到连续物理页。连续内存分配器CAM使得这种情况下分配大的连续内存块成为可能。
1、一种解决方案是为设备保留一块大的内存区域:缺点 当设备驱动不使用的实时,内核其他模块也不能使用这块内存;
2、连续内存分配试图解决这个问题,保留一块大的内存区域。当设备驱动不使用的时候,内核其他模块可以使用,要求:只有申请可移动类型的页时可以借用;当设备驱动需要使用的时候,把已经分配的页迁移到其他地方,形成物理连续的大内存块。
CMA区域分为全局CMA区域和设备私有CMA区域。全局CMA区域是由所有设备共享的,设备私有CMA区域由指定的一个或多个设备驱动使用。
使用内核参数cma=nn[MG]@[start[MG]][-end[MG]]设置全局CMA区域的大小和物理地址范围
CONFIG_CMA_SIZE_SEL_MBYTES表示兆字节;0表示禁用
CONFIG_CMA_SIZE_SEL_PERCENTAGE 表示指定物理内存容量的百分比,默认使用指定兆字节数的方式;0表示禁用
以上两种方式都可以使用内存传递参数启用CMA
如果子节点的属性“compatible”的值是shared-dma-pool 表示全局CMA区域,否则表示设备私有CMA区域
reserved-memory {
#address-cells= <1>;
#size-cells= <1>;
ranges ;
linux , cma {
compatible= " shared-dma-pool" ;
reusable;
size= ;
alignment= ;
linux , cma-defaul 七;
} ;
display_reserved: framebuffer@78000000 {
reg= ;
) ;
multimedia reserved : multimedia@77000000
compatible= "acme, multimedia-memory" ;
reg= ;
} ;
) ;
分配三个cma区域,
连续内存分配器是DMA映射框架的辅助框架,设备驱动程序不能直接使用连续分配器;
dma_alloc_from_contiguous 用来从CMA分配
dma_release_from_contiguous 释放
dma_alloc_coherent ,dma_alloc_noncoherent 用来分配内存
dma_free_conerent ,dma_free_nocoherent用来释放内存
可配置多个CMA区域,内核定义一个数组来管理CMA区域
struct cma cma_areas[MAX_CMA_AREAS];
unsigned cma_area_count;
页分配器为CMA区域的物理页定义了迁移类型MIGRATE_CMA
内存管理子系统初始化,解析设备树二进制文件得到物理内存布局,使用memblock保存布局信息。
memblock的memory保存物理块的物理地址范围,
reserved类型保存预留内存块的物理地址范围
CMA区域属于保留内存块
通过设备树配置CMA区域,解析如下:
setup_arch->arm64_memblock_init
early_init_fdt_scan_reaseved_mem
memblock是内核初始化的时候使用的内存分配器,内核初始化完成后使用伙伴分配器管理物理页。内核初始化后,把空闲的内存释放给伙伴分配器,不会把保留的内存释放给伙伴分配器。CMA是保留内存。但需要把CMA区域的物理页交给伙伴分配器管理。
当设备驱动程序不使用CMA区域的时候,内核的其他模块可以借用CMA区域的物理页,页分配器只允许可移动类型从CMA类型
借用物理页。
1)从迁移类型分配页
2)如果分配失败,从备用类型借用物理页
如果指定迁移类型是可移动类型,首先从CMA类型借用物理页
从备用类型列表中的每个迁移类型借用物理页
当设备驱动程序需要使用CMA区域的时候,如果CMA区域的物理页已经被页分配器分配出去,需要把物理页迁移到其他地方。