一、DMA-BUF等概念的介绍

首先需要明确DMA-BUF,Dma buffer,ION和DMA-BUF Heap是不同的概念。

在Android 多媒体系统中为了减少因不同进程之间内存的多次拷贝而产生的不必要的开销,最直接的想法是希望跟硬件设备进行交互的应用能有一个内存能跟设备驱动程序共享数据,理想情况是这个buffer能够直接是通过memory map得到,并且是物理连续的,这样就能让DMA直接读写这块buffer,减少CPU或者外设来访问内存的开销。

为此kernel引入了DMA-BUF这个框架(或者说是子系统),来解决CPU和各种不同外设驱动之间buffer共享的问题。

  • 其中Dma buffer是一块允许在CPU和其他子系统或各种IO外设间共享的buffer。

  • 而DMA-BUF是这个buffer的描述和使用框架。框架提供了对dma-buffer的描述结构体,和基于file的dma-buf使用接口,同时完成了操作时刷cache的动作。

DMA-BUF框架实现了一个dma-buf的文件系统(filesystem),这个文件系统直接通过调用挂载接口挂载到了内核(没有提供挂载节点),每个dma-buf实例,会在文件系统中创建出inode及file,并将fd返回给调用者。调用者通过对file的ioctrl、map等操作,来操作dma-buffer。

也就是说为了实现buffer的共享,DMA-BUF将buffer与file关联起来,通过file来间接的引用和共享buffer, 即 dma-buf 既是块物理 buffer,又是个 linux file。buffer 是内容,file 是媒介,只有通过 file 这个媒介才能实现同一 buffer 在不同驱动之间的流转。

代码位置:

common/driver/dma-buf/
//或
/kernel/msm-5.4/drivers/dma-buf/dma-buf.c

如上图中所示,在DMA-BUF框架中有两个很重要的概念,一个是exporter,另一个是importer。

dma buffer 本身由 DMA-BUF exporter 创建,DMA-BUF exporter 是一个驱动程序,它可以分配特定类型的内存,而且还为 kernel、user space、device 提供了多种回调函数来处理 buffer 的 map 和 unmap 问题,所以exporter相当于一个buffer的生产者或者说是提供者。

而DMA-BUF importer则对应dma buffer的使用者,比如上层应用,而因为dma buffer是一种共享内存,所以同一个buffer的importer可以有多个,二者的特性说明:

  1. exporter:

    • 实现struct dma_buf_ops中的buffer管理回调函数;
    • 允许其他消费者通过dma-buf的sharing APIS来共享buffer缓冲区;
    • 通过struct dma_buf结构体管理buffer的分配、包装等细节工作;
    • 决策buffer的实际后端内存的来源;
    • 管理scatterlist迁徙;
  2. importer:

    • 是共享buffer的使用者之一;
    • 无需担心缓冲区是如何/在哪里创建的;
    • 通过struct dma_buf_attachment结构体访问用于构建buffer的scatterlist,并且提供将buffer映射到自己地址空间的机制,这样可以访问到内存的同块区域,实现共享内存

二、基于DMA-BUF框架的内存分配器

过去几年中,Android系统里面已经使用过多种DMA buffer分配方案:首先是PMEM,然后被Android 系统下专用于分配 Graphic Buffer 的内存分配器ION所替换。

ION 是基于 DMA-BUF 实现的,可以在多个设备之间实现 buffer 共享,它的代码一直存放在 staging 目录下,不过再过几年可能就不复存在了,因为ION自从2012年开始商用以来也存在着不少问题。

随后John Stultz发布了一个patch set,实现了DMA-BUF heap,是ION的一个演进版本,在之前的 Android 12 中,GKI 2.0 将 ION 分配器已经被替换为了 DMA-BUF Heap,因为DMA-BUF HEAP的分配器具有更具有稳定的 ABI和安全性,也更标准化。

综上需要明确的是,不管是ION还是DMA-BUF heap都是基于DMA-BUF框架的一种分配器allocator,也就是说ION和DMA-BUF heap是上面DMA-BUF中提到的exporter驱动。

  1. ION分配器:
    ION是基于DMA-BUF框架实现的一种内存分配器,在多媒体部分中使用的最多,从 Camera 到 Display,从 Mediaserver 到 Surfaceflinger,都会利用 ION 进行内存分配管理。

ION提供了多个memory pool,称为“heaps”。它们有不同的属性,例如有的是物理连续的,有的不是。这些heap包括“system”heap,用来供vmalloc_user()分配;“system_contig”h eap,是用kzalloc()分配的。还有“carveout” heap,是在启动阶段就额外划分出来的物理连续区域。应用程序可以用一些user space的API来对这些heap分配、释放、共享内存。

ION的特点是它可以被用户空间的进程之间或者内核空间的模块之间进行内存共享,且这种共享方式是零拷贝的。

代码位置:

//本文的许多结构都是以内核4.14(kernel-4.14)为例,因为在内核5(kernel-5.10)以后的版本中,ION逐渐被弃用,许多代码已经不太相同
common/drivers/staging/android/ion/
kernel-4.14/drivers/staging/android/ion/
//或
/kernel/msm-5.4/drivers/staging/android/ion/
kernel-5.10/drivers/staging/android/ion/

ION 是在各种 heaps 上分配内存,通过 ion_buffer 来描述所分配的内存。

每个heap中分配了若干个buffer,不同的client是通过文件描述符fd来实现内存共享的。

ION是在各种heaps上分配内存,其中定义了四种不同的heap,实现不同的内存分配策略。

  • ION_HEAP_TYPE_SYSTEM : 通过vmalloc分配内存(vmalloc : 虚拟地址连续但物理不连续内存)
  • ION_HEAP_TYPE_SYSTEM_CONTIG: 通过kmalloc分配内存(kmalloc : 物理连续内存)
  • ION_HEAP_TYPE_CARVEOUT: 在保留内存块中(reserve memory)分配内存
  • ION_HEAP_TYPE_CUSTOM: 由客户自己定义
  1. DMA-BUF heaps分配器:
    DMA-BUF heaps也是一种基于DMA-BUF框架实现的内存分配器,是一种取代ION分配的方式。

ION开发的时候,kernel也有一个DMA buffer sharing (DMA-BUF)的API在同时进行开发,此外还有contiguous memory allocator (CMA)。所以功能上有些重复。此外,ION起初是在32-bit ARM处理器上为Android开发的,所以用了一些ARM特有的kernel API。这些都是合入linux mainline的阻碍。而这个新的基于DMA-BUF heap的patch就对ION的内部实现做了彻底的重构,使用CMA来基于某个特殊内存区域实现物理连续heap,也不再使用ARM特有的函数了。patch set还带了一个self-test,展示了API是如何使用的。

DMA-BUF Heap的代码主要位置:

common/driver/dma-buf/heaps/
//主要文件
common/include/linux/dma-heap.h
common/include/uapi/linux/dma-heap.h
common/driver/dma-buf/dma-heap.c            //或/msm-kernel/drivers/dma-buf/dma-heap.c
common/drivers/dma-buf/heaps/system_heap.c
common/drivers/dma-buf/heaps/cma_heap.c

三、ION heap和 DMA-BUF heap的区别

  1. 分配方式不同
  • ION需要指定堆 ID/掩码和标志(heap id和heap flag)才能进行分配。

  • DMA-BUF heap只需要指定heap的名称就能分配内存

  1. DMA-BUF heap可通过不同的字符设备名控制访问权限,更安全
  • 对于 ION heap而言,所有的内存分配都是从通过访问同一个字符设备 /dev/ion 来完成的。

  • 对于DMA-BUF heap来说,每个DMA-BUF heap都对应生成一个位于/dev/dma_heap/<heap_name> 的字符设备,因此可以通过 sepolicy 单独控制对每个堆的访问权限。

  1. DMA-BUF heap不支持堆专用标志,所以更容易对外提供统一的接口,利于标准化
  • 对于ION heap来说,会通过专用标志来实现不同的内存分配策略。

如ION 在 SYSTEM_HEAP 上分配内存时,使用ION_HEAP_SYSTEM来分配,而对于是否分配带 cache 的 buffer,则是通过传入 ION_FLAG_CACHED 标志位来实现的。(也就是说可以支持同一个heap中传入vendor私有的heap flags来实现不同的分配方式)

//ION中系统堆中的缓存分配
//libion
ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, ION_FLAG_CACHED, &fd)

因为是专用标志,也就是私有化,不同的vendor厂商实现不同不容易统一。

  • 对于 DMA-BUF heap来说,则不支持堆的专用标志。每种不同的分配都是在不同的堆中完成的。

例如,对于在ION中system heap的cached和uncached两种分配方式在DMA-BUF heap中则是会生成两个独立的heap: /dev/dma_heap/system 和 /dev/dma_heap/system_uncached

//DMA-BUF中系统堆中的缓存分配
//libdmabufheap
allocator->Alloc("system", size)

对于HEAP堆类型的简单说明:

  • CMA HEAP(物理连续 buffer)

  • SYSTEM HEAP(物理非连续 buffer)
    SYSTEM HEAP 默认只支持带 Cached 的 buffer,只有 CPU 需要参与访问的 buffer 才需要带 cached,这样可以加快 CPU 的访问速度,但是在 CPU 和 DMA 设备之间共享内存时,需要来回刷 Cache,这会增加系统开销。

  • SYSTEM-UNCACHED HEAP(应用程序申请不带 cache 的 buffer)
    不带 cached 的 buffer 则通常只用于 DMA 设备之间的 buffer 共享,因此省去了 Cache 同步所带来的额外开销,极大的提高了 DMA 设备访问 buffer 的效率。


参考

dma-buf 由浅入深(八) —— ION 简化版

Buffer Sharing and Synchronization

Camera Buffer Management

dma-heap: Add a system-uncached heap

DMA_HEAP源码

201_DMA-BUF简单介绍相关推荐

  1. MessageDigest简单介绍

    本文博客原文 參考文章:http://blog.sina.com.cn/s/blog_4f36423201000c1e.html 一.概述 java.security.MessageDigest类用于 ...

  2. AES方式加解密的简单介绍

    上面一篇文章介绍了使用DES方式进行加解密( DES方式加解密的简单介绍),我们说了DES由于使用8个字节(64bit)密钥进行加解密,所以安全性不够(当然这里的不够都是相对的),所以现在使用了密钥更 ...

  3. Socket编程之简单介绍 - 蓝天下的雨 - 博客园

    Socket编程之简单介绍 - 蓝天下的雨 - 博客园 Socket编程之简单介绍 - 蓝天下的雨 - 博客园 Socket编程之简单介绍 2013-03-19 15:27 by 蓝天下的雨, 878 ...

  4. 遗传算法的简单介绍以及模式定理的简单证明

    遗传算法   遗传算法(Genetic Algorithm,GA),最早是由美国的John holland在20世纪70年代提出.算法通过模拟达尔文生物进化论的自然选择以及遗传学机理的生物进化过程来搜 ...

  5. 2021年大数据ELK(十八):Beats 简单介绍和FileBeat工作原理

    全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 Beats 简单介绍和FileBeat工作原理 一.Beats 二.FileB ...

  6. 2021年大数据ELK(十五):Elasticsearch SQL简单介绍

    全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 Elasticsearch SQL简单介绍 一.SQL与Elasticsear ...

  7. 2021年大数据ELK(二):Elasticsearch简单介绍

    全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 一.Elasticsearch简介 1.介绍 2.创始人 二.E ...

  8. iOS开发UI篇—多控制器和导航控制器简单介绍

    iOS开发UI篇-多控制器和导航控制器简单介绍 一.多控制器 一个iOS的app很少只由一个控制器组成,除非这个app极其简单.当app中有多个控制器的时候,我们就需要对这些控制器进行管理 有多个vi ...

  9. 简单介绍一下R中的几种统计分布及常用模型

    统计学上分布有很多,在R中基本都有描述.因能力有限,我们就挑选几个常用的.比较重要的简单介绍一下每种分布的定义,公式,以及在R中的展示. 统计分布每一种分布有四个函数:d――density(密度函数) ...

  10. LVS(Linux Virtual Server)三种负载均衡模型和十种调度的简单介绍

    LVS(Linux Virtual Server)三种负载均衡模型和十种调度的简单介绍 LVS (Linux Virtual Server) LVS(Linux Virtual Server)其实就是 ...

最新文章

  1. ologit模型与logit_Stata-多元 Logit 模型详解 (mlogit)
  2. java高并发下的数据安全
  3. [原创].NET 分布式架构开发实战之一 故事起源
  4. python编程求导数_面向对象编程 —— java实现函数求导
  5. 华三H3c 交换机 vlan Hybird端口配置
  6. 第五讲 C#中的异常处理
  7. PHP中self和static的区别,php面向对象程序设计中self与static的区别分析
  8. python中fg是什么意思_Python fg
  9. 通达信手机版服务器文件夹,【通达信】通达信的一些目录和系统文件,用法说明。以备查询。...
  10. 为资产分类定义折旧范围_2广东省农村集体经济组织固定资产分类及折旧办法(4月15日)...
  11. 苹果手机铃声制作教程
  12. android 长按复制,【转】TextView长按复制实现方法小结
  13. 英文学习20180529
  14. 微软WIN7系统瘦身全攻略
  15. 抖音+今日头条副业项目,新玩法,后期收益月入过万
  16. 百万excel导入mysql_百万级xlsx表格导入数据库的实现方案
  17. UNIX环境高级编程(1)——UNIX系统总览
  18. 发邮件抛异常。no object DCH for MIME type text/plain; charset=UTF-8
  19. LinkedIn领英帐号搜索浏览被限制的解决方法
  20. 京东优惠券查询API接口接入方案,item_search_coupon - 京东优惠券查询接口

热门文章

  1. 潮人篮球不显示服务器,潮人篮球补篮技巧详解
  2. 线性代数 --- 投影Projection与Cauthy-Schwarz柯西不等式(个人学习笔记)
  3. Matlab实现——严格对角占优三对角方程组求解(高斯赛尔德Gauss-Seidel迭代、超松弛)
  4. 自学数据结构_五月十日_综述
  5. java断路器原理_Netflix Hystrix断路器原理分析
  6. python describe函数_Python pandas.DataFrame.describe函数方法的使用
  7. python正则表达式(一)
  8. DA, DH, MDA, MDH,MSA到底是什么
  9. 台湾李宏毅教授深度学习
  10. 【前端页面缓存技术方案】