目录

什么是CMA

数据结构

CMA区域 cma_areas 的创建

dts方式

command line方式

将CMA区域添加到Buddy System

CMA分配


《Linux内存管理:什么是CMA(contiguous memory allocation)连续内存分配器?可与DMA结合使用》

《Linux内存管理:CMA(连续内存分配)》

《Linux 内存管理之CMA》

什么是CMA


CMA是reserved的一块内存,用于分配连续的大块内存。

  • 当设备驱动不用时,内存管理系统将该区域用于分配和管理可移动类型页面;
  • 当设备驱动使用时,此时已经分配的页面需要进行迁移,又用于连续内存分配

其用法与DMA子系统结合在一起充当DMA的后端,具体可参考《没有IOMMU的DMA操作》。

数据结构


struct cma {//CMA区域物理地址的起始页帧号unsigned long   base_pfn; //CMA区域总体的页数unsigned long   count;//位图,用于描述页的分配情况unsigned long   *bitmap;//位图中每个bit描述的物理页面的order值,其中页面数为2^order值unsigned int order_per_bit; /* Order of pages represented by one bit */struct mutex    lock;
#ifdef CONFIG_CMA_DEBUGFSstruct hlist_head mem_head;spinlock_t mem_head_lock;
#endifconst char *name;
};extern struct cma cma_areas[MAX_CMA_AREAS];
extern unsigned cma_area_count;
  • bitmap来管理其内存的分配,0表示free,1表示已经分配。

  • 如果order_per_bit等于0,表示按照一个一个page来分配和释放,如果order_per_bit等于1,表示按照2个page组成的block来分配和释放,以此类推。

  • count说明该cma_areas内存有多少个page。它和order_per_bit一起决定了bitmap指针指向内存的大小。

  • base_pfn定义了该cma_areas的起始page frame number,base_pfn和count一起定义了该cma_areas在内存中的范围。

CMA区域 cma_areas 的创建


CMA区域的创建有两种方法,一种是通过dts的reserved memory,另外一种是通过command line参数和内核配置参数。

dts方式


reserved-memory {/* global autoconfigured region for contiguous allocations */linux,cma {compatible = "shared-dma-pool";reusable;size = <0 0x28000000>;alloc-ranges = <0 0xa0000000 0 0x40000000>;linux,cma-default;};
};

device tree中可以包含reserved-memory node,系统启动的时候会打开rmem_cma_setup

RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);

command line方式


cma=nn[MG]@[start[MG][-end[MG]]]

static int __init early_cma(char *p)
{pr_debug("%s(%s)\n", __func__, p);size_cmdline = memparse(p, &p);if (*p != '@') {/*if base and limit are not assigned,set limit to high memory bondary to use low memory.*/limit_cmdline = __pa(high_memory);return 0;}base_cmdline = memparse(p + 1, &p);if (*p != '-') {limit_cmdline = base_cmdline + size_cmdline;return 0;}limit_cmdline = memparse(p + 1, &p);return 0;
}
early_param("cma", early_cma);

系统在启动的过程中会把cmdline里的nn, start, end传给函数dma_contiguous_reserve,流程如下:

setup_arch--->arm64_memblock_init--->dma_contiguous_reserve->dma_contiguous_reserve_area->cma_declare_contiguous

将CMA区域添加到Buddy System


为了避免这块reserved的内存在不用时候的浪费,内存管理模块会将CMA区域添加到Buddy System中,用于可移动页面的分配和管理。CMA区域是通过cma_init_reserved_areas接口来添加到Buddy System中的。

static int __init cma_init_reserved_areas(void)
{int i;for (i = 0; i < cma_area_count; i++) {int ret = cma_activate_area(&cma_areas[i]);if (ret)return ret;}return 0;
}
core_initcall(cma_init_reserved_areas);

其实现比较简单,主要分为两步:

  1. 把该页面设置为MIGRATE_CMA标志

  2. 通过__free_pages将页面添加到buddy system中

CMA分配


《没有IOMMU的DMA操作》里讲过,CMA是通过cma_alloc分配的。cma_alloc->alloc_contig_range(..., MIGRATE_CMA,...),向刚才释放给buddy system的MIGRATE_CMA类型页面,重新“收集”过来。

用CMA的时候有一点需要注意

也就是上图中黄色部分的判断。CMA内存在分配过程是一个比较“重”的操作,可能涉及页面迁移、页面回收等操作,因此不适合用于atomic context。比如之前遇到过一个问题,当内存不足的情况下,向U盘写数据的同时操作界面会出现卡顿的现象,这是因为CMA在迁移的过程中需要等待当前页面中的数据回写到U盘之后,才会进一步的规整为连续内存供gpu/display使用,从而出现卡顿的现象。

https://mp.weixin.qq.com/s?__biz=MzIxMjE1MzU4OA==&mid=2648924073&idx=1&sn=bbaf5db820a1ef77b4b0e4190a816040&chksm=8f5d9a32b82a132499513fc05e637257aa7883010207d3593dd292f46cd2f69bbf4d0f32154f&token=1349594618&lang=zh_CN&scene=25#wechat_redirect

Linux内存管理:CMA(连续内存分配)(DMA)相关推荐

  1. Linux内核机制总结内存管理之连续内存分配器(二十七)

    文章目录 1 连续内存分配器 1.1 使用方法 1.2 技术原理 重要:本系列文章内容摘自<Linux内核深度解析>基于ARM64架构的Linux4.x内核一书,作者余华兵.系列文章主要用 ...

  2. 操作系统【三】内存管理基础+连续内存分配

    内存的基础知识 内存分为按字节编址(8位)和字编制(不同计算机不一样,64位计算机就是64位,即8个字节) 相对地址=逻辑地址 绝对地址=物理地址 从逻辑地址到物理地址的转换由装入解决. 装入的三种方 ...

  3. 【清华大学】操作系统 陈渝 Part3 ——物理内存管理 之 连续内存分配

    [清华大学]操作系统 陈渝 Part3 --物理内存管理 之 连续内存分配 3.1计算机体系结构及内存分层 计算机体系机构 内存体系层次 管理内存方法 3.2地址空间 & 地址生成 地址空间定 ...

  4. linux进程管理内存管理,Linux专业知识四:Linux系统进程管理及查看内存

    本文主讲Linux专业知识之Linux系统进程管理及查看内存的情况,以Redhat RHEL7操作系统为例. 一.进程 程序与进程:程序是静态的(文件),进程是动态的(运行的程序). 进程和线程:一个 ...

  5. 【Linux 内核 内存管理】优化内存屏障 ③ ( 编译器屏障 | 禁止 / 开启内核抢占 与 方法保护临界区 | preempt_disable 禁止内核抢占源码 | 开启内核抢占源码 )

    文章目录 一.禁止 / 开启内核抢占 与 方法保护临界区 二.编译器优化屏障 三.preempt_disable 禁止内核抢占 源码 四.preempt_enable 开启内核抢占 源码 一.禁止 / ...

  6. Java内存管理:Java内存区域 JVM运行时数据区

    Java内存管理:Java内存区域 JVM运行时数据区 在前面的一些文章了解到javac编译的大体过程.Class文件结构.以及JVM字节码指令. 下面我们详细了解Java内存区域:先说明JVM规范定 ...

  7. 属性与内存管理(属性与内存管理都是相互关联的)

    <span style="font-size:18px;"> 属性与内存管理(属性与内存管理都是相互关联的)第一部分一,属性:属性是OC2.0之后出来的新语法,用来取代 ...

  8. JVM自动内存管理机制——Java内存区域(下)

    一.虚拟机参数配置 在上一篇<Java自动内存管理机制--Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...

  9. 95-290-050-源码-内存管理-堆外内存与堆内内存概述

    2.概述 ​ Flink的内存管理器管理着用于排序.散列和缓存所需的内存.内存以相等大小的(Segments)表示,称为内存页.操作器通过请求多个内存页来分配内存.在Flink中,内存又分为堆内存和非 ...

  10. C++:内存管理:C++内存管理详解

    C++语言内存管理是指:对系统的分配.创建.使用这一系列操作.在内存管理中,由于是操作系统内存,使用不当会造成很麻烦的后果.本文将从系统内存的分配.创建出发,并且结合例子来说明内存管理不当会造成的结果 ...

最新文章

  1. python绘制直方图显示数字_Python实现绘制双柱状图并显示数值功能示例
  2. SpringMVC框架 学习DAY_02 : 接收请求参数/向模板页面转发数据/重定向与转发 /Session
  3. 【Opencv实战】入门也能学会的「黑白上色」教程与手法核心~(收藏不谢)
  4. 《你不知道的JavaScript(上卷)》读书笔记
  5. 产品原型制作_早期制作原型如何帮助您设计出色的数字产品
  6. nodejs里的module.exports和exports
  7. JavaScript设计模式之构造器、模块和原型
  8. PHP基础知识系统复习
  9. php判断号码归属,php手机号码归属地查询
  10. 查看DBUS接口的工具: D-Feet
  11. RAC环境备份归档日志和RMAN恢复启动数据库
  12. OSC源创会(西安)图文总结
  13. 风云邀请成为IT168社区Silverlight版主
  14. 数字电子技术1:数字逻辑概论
  15. STEP7 V5.7安装包下载链接及安装教程
  16. macos系统里面,蓝牙鼠标偶尔卡顿,飘的问题
  17. 未来社区系统整体解决方案
  18. 西门子PLC 的特殊功能寄存器
  19. 神经网络模型优化方法(缓解过拟合)
  20. 服装厂仓库货存经常丢失?环境监测技术可助力仓库管理

热门文章

  1. c程序设计停车场收费管理系统_智能车牌识别停车收费管理系统
  2. Spring框架----自动按照类型注入的Autowired注解
  3. .Net Core 商城微服务项目系列(十四):分布式部署携程Apollo构建配置中心
  4. html 自定义标签的作用
  5. maven2打包不同jdk版本的包
  6. Struts+iBatis+Spring+mysql整合开发
  7. .Net 平台下的版本控制 --- Subversion(SVN)1.6.x
  8. vb中调用aspx页面
  9. linux链接时报未定义的引用,g ++链接或引用不与本地安装的库一起使用:未定义的引用...
  10. 地图旋转_如何使用万能地图下载器计算七参数