当前位置: 首页 > news >正文

内存管理(三)--Linux CMA内存使用

文章目录

  • 一、预留一段内存常用方法
    • 1.1 设备树定义reserve memory
  • 二、内存节点常见属性
    • 2.1 no-map和reusable使用上的区别
  • 三、预留CMA的reserved memory方法
    • 3.1 共享cma(采用设备树)
    • 3.2 共享cma(采用bootargs)
    • 3.3 私有cma
  • 四、使用reserved memory


我们日常使用kmalloc最多只能动态申请到4M(2^order)内存,当我们需要大块连续内存时,就需要借助CMA申请大内存。
CMA内存分配器在系统中具有多种重要作用,包括分配连续大块内存、提高内存利用率、提供灵活性与可迁移性、优化性能以及简化内存管理等。这些作用共同使得CMA成为嵌入式系统和其他需要连续内存支持的应用场景中的重要技术之一。

前文讲了Linux几种内存预留方法,本文主要讲解Linux里预留CMA内存方法和使用。


一、预留一段内存常用方法

1.1 设备树定义reserve memory

如果需要保留一段内存,在reserved-memory 节点下定义新节点。

reserved-memory {#address-cells = <0x2>;#size-cells = <0x2>;...fb_reserved0: framebuffer{reg = <0x1 0x10000000 0x0 0x8000000>; //addr:0x110000000  128M... //指定这个内存的属性,如:no-map, reusable};....};      

如果要将这个内存私有指定设备里,由指定设备节点使用,通过memory-region字段进行引用(指定给节点fb1使用):

  fb1 {compatible = "xx,xxx";memory-region = <&fb_reserved0>;  //引用这段内存私有到这个设备interrupt-parent = <&gic>;interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;interrupt-names = "xx";...};

二、内存节点常见属性

预留内存可以指定常用的属性,常见有:
1. reusable:表示当前的内存区域除了被dma使用之外,还可以被内存管理(buddy)子系统reuse。
2. no-map:表示是否需要创建页表映射,对于通用的内存,必须要创建映射才可以使用,共享CMA是可以作为通用内存进行分配使用的,因此必须要创建页表映射。
3. linux,cma-default:如果要cma区域为共享区域,需要配置上linux,cma-default属性。 指定了 linux,cma-default 属性,内核在分配 cma 内存时会将这片内存当成默认的 cma 分配池使用,执行内存申请时如果没有指定对应的 cma 就使用默认 cma pool。
4. alignment:对齐参数,保留内存的起始地址需要向该参数对齐
5. alloc-ranges:指定可以用来申请动态保留内存的区间.
6. shared-dma-pool(compatible="shared-dma-pool")
有的时候设备驱动程序需要采用DMA的方式使用预留的内存,对于这种场景,可以dts中的节点属性设置为shared-dma-pool,从而生成为特定设备驱动程序预留的DMA内存池。这样,设备驱动程序仅需要以常规方式使用DMA API。

2.1 no-map和reusable使用上的区别

如上已经介绍了no-map和reusable的特点,显著区别在于这几点:

  1. 是否需要将这块内存进行系统管理,放入buddy中管理。
  2. no-map保留的内存区域已被内核排除,因此iomem信息(/proc/iomem)显示系统RAM小于主板中的内存量。
  3. no-map由于没有创建映射表,因此使用时需要通过ioremap/ioremap_nocache
    /memremap等方式将内存映射出使用。

三、预留CMA的reserved memory方法

cma内存可以理解为是借用了reserve memory节点,可以使用DMA通用映射框架的API对其内存进行申请和使用。
编译内核时需要开启以下配置宏使用cma:

(1)配置宏CONFIG_CMA,启用连续内存分配器。
(2)配置宏CONFIG_CMA_AREAS,指定CMA区域的最大数量,默认值是7。
(3)配置宏CONFIG_DMA_CMA,启用允许设备驱动分配内存的连续内存分配器

cma内存可以将reserve memory分为私有cma和共享cma区域。

3.1 共享cma(采用设备树)

共享cma,将从系统全局自动配置一个连续分配区域 ,所有设备驱动在需要cma内存的时可以从这里面申请,不需要的时候,将作为buddy给系统使用。
标准定义方法如下,定义节点为linux,cma节点定义属性为:shared-dma-pool,reusable,linux,cma-default

reserved-memory {  / / 需要预留内存放在这个reserved-memory节点内定义#address-cells = <0x2>;#size-cells = <0x2>;ranges;cma_reserved: linux,cma {compatible = "shared-dma-pool";reusable;//表示 cma 内存可被 buddy 系统使用size = <0x0 0x80000000>; // 2GBalignment = <0x0 0x2000>; // 8KBlinux,cma-default; //作为cma默认内存池};....
};

3.2 共享cma(采用bootargs)

共享cma也通过内核参数“cma”配置全局CMA区域的大小。
使用内核参数“cma=nn[MG]@[start[MG][-end[MG]]]”设置全局CMA区域的大小和物理地址范围。

3.3 私有cma

reserved memory除了共享cma以外定义方式,其他认为是私有cma。个人认为,为方便区分,cma内存通常指共享池的cma,其他方式的就都称为reserved内存。
如上3.1 案例就是私有cma预留方式,通常配合各种属性对这个内存进行定义。


四、使用reserved memory

当内存compatible为shared-dma-pool。这时候设备驱动程序可以采用DMA的方式去使用预留的内存

  1. 设置设备寻址能力mask: dma_set_coherent_mask/dma_set_mask(一致/非一致性) 。这个会影响cma申请地址大小:2^mask。
  2. 通过of_reserved_mem_device_init来将从设备树memory-region获取内存地址私有化到设备里。
  3. 驱动通过接口dma_alloc_coherentdma_alloc_noncoherent(一致/非一致性)用来分配内存,接口dma_free_coherent和dma_free_noncoherent用来释放内存。

其他类型的内存需要通过如:ioremap/ioremap_nocache/memremap等,映射出内存地址使用。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 巧用xrename批量重命名下载的影视文件
  • SQL-函数
  • Open3D 基于曲率大小的特征点提取
  • 微信小程序中如何监听元素进入目标元素
  • stm32F103 串口2 中断 无法接收指定字符串 [已解决]
  • 用idea写Spark程序时,想要在控制台打印日志?
  • class 6: vue.js 3 组件化开发
  • 微服务--Nacos配置管理
  • axios返回的是promise对象如何处理?
  • Mysql高阶语句(1)
  • Python教程:使用 Python 和 PyHive 连接 Hive 数据库
  • HALCON 错误代码 #7709
  • 缓存分布式一致性问题
  • Golang 小项目(3)
  • 【重学 MySQL】六、MySQL 的下载、安装、配置
  • 自己简单写的 事件订阅机制
  • [NodeJS] 关于Buffer
  • 〔开发系列〕一次关于小程序开发的深度总结
  • Angular数据绑定机制
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • Java精华积累:初学者都应该搞懂的问题
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • tab.js分享及浏览器兼容性问题汇总
  • Web设计流程优化:网页效果图设计新思路
  • windows下使用nginx调试简介
  • 不上全站https的网站你们就等着被恶心死吧
  • 从伪并行的 Python 多线程说起
  • 大数据与云计算学习:数据分析(二)
  • 高度不固定时垂直居中
  • 深度解析利用ES6进行Promise封装总结
  • 实现简单的正则表达式引擎
  • 通过git安装npm私有模块
  • 我有几个粽子,和一个故事
  • FaaS 的简单实践
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • #QT项目实战(天气预报)
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • $.ajax()参数及用法
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (STM32笔记)九、RCC时钟树与时钟 第二部分
  • (蓝桥杯每日一题)love
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (十六)串口UART
  • (一)插入排序
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • .bat批处理(四):路径相关%cd%和%~dp0的区别
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET 读取 JSON格式的数据