ION的设计初衷

Android为了更好的针对移动设备内存的管理,设计出了ION内存管理机制,主要是为了解决以下几个问题:

  • 预留大块连续内存,比如camera,display,GPU等模块
  • 避免内存随便花
  • 用户控件和硬件之间实现”零拷贝”(zero-copy)的内存共享 做Android系统的,特别是跟Display,camera模块相关的

ION的官方介绍和历史由来查看下面的介绍:

https://lwn.net/Articles/480055/

ION的实现

Android系统的ION实现依赖于不同的CPU/GPU硬件,Android提供了ION的框架供CPU厂商(NXP, Qualcomm, MTK, 海思等)在自己的BSP里面实现ION机制。

默认的ION驱动会提供以下三种不同的ION heaps实现:

  • ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc_user()
  • ION_HEAP_TYPE_SYSTEM_CONFIG: memory allocated via kzalloc
  • ION_HEAP_TYPE_CARVEOUT: carveout memory is physically contiguous and set aside at boot

CPU厂商会根据自己CPU的特性实现更多的ION heaps,比如NVIDIA提交了一种ION_HEAP_TYPE_IOMMU的heap。

不管哪一种ION heaps实现,都必须实现如下核心接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct ion_heap_ops {int (*allocate)(struct ion_heap *heap,struct ion_buffer *buffer, unsigned long len,unsigned long align, unsigned long flags);void (*free)(struct ion_buffer *buffer);int (*phys)(struct ion_heap *heap, struct ion_buffer *buffer,ion_phys_addr_t *addr, size_t *len);struct sg_table * (*map_dma)(struct ion_heap *heap,struct ion_buffer *buffer);void (*unmap_dma)(struct ion_heap *heap, struct ion_buffer *buffer);void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer,struct vm_area_struct *vma);int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan);void (*unmap_user) (struct ion_heap *mapper, struct ion_buffer *buffer);int (*print_debug)(struct ion_heap *heap, struct seq_file *s,const struct list_head *mem_map);
};

简单概括一下

  • allocate()free()分别用来从heap中分配或者释放一个ion_buffer对象
  • 连续的物理内存,phys()用来得到ion_buffer对象的物理内存地址和大小
  • map_kernel()unmap_kernel()分别用来把物理内存映射到内核虚拟地址空间
  • map_user()用来把物理内存映射到用户空间,当用户空间的文件描述符被释放的时候会自动取消映射,所以没有提供类似于unmap_user()的函数

用户空间进程使用ION的情形

主要数据结构

在整个Android操作系统中,可以发现,比较好的框架,先去了解数据结构,就能猜到是如何实现的整个架构。

ion_device

ion_device是ION驱动的最基础的一个对象,用来描述一个ion设备,其实在一个Android操作系统中,一般只有一个实例存在,用来统一管理ION Heaps,由CPU厂商自己的代码来创建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct ion_device {struct miscdevice dev;struct rb_root buffers;struct mutex buffer_lock;struct rw_semaphore lock;struct plist_head heaps;long (*custom_ioctl)(struct ion_client *client, unsigned int cmd,unsigned long arg);struct rb_root clients;struct dentry *debug_root;struct dentry *heaps_debug_root;struct dentry *clients_debug_root;struct semaphore vm_sem;atomic_t page_idx;struct vm_struct *reserved_vm_area;pte_t **pte;...
};

struct ion_device是ION的核心结构体,但是在用户空间是不可见的,是由CPU厂商的代码通过ion_device_create()函数分配、初始化。

  • dev成员,是一个struct miscdevice类型的杂项字符设备,用来连同内核和用户空间,open/ioctl
  • heaps成员,用来描述所有的struct ion_heap实例
  • clients成员,用来管理所有struct ion_client

ion_client

struct ion_client是由ion_client_create()创建,是通过struct ion_device来创建的。

1
2
3
4
5
6
7
8
9
10
11
12
13
struct ion_client {struct rb_node node;struct ion_device *dev;struct rb_root handles;struct idr idr;struct mutex lock;const char *name;char *display_name;int display_serial;struct task_struct *task;pid_t pid;struct dentry *debug_root;
};
  • node成员,用于将struct ion_client实例加入到struct ion_deviceion_device::clients
  • device成员,指向设备的ion_device
  • handles成员,是一个红黑树的根,用来管理它所拥有的handle,即struct ion_handle实例。一个struct ion_handle实例代表一个buffer。ion_buffer是从struct ion_heap中分配的。

ion_heap

struct ion_heap表示ION中的heap,被ion_device中的ion_device::heaps所管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct ion_heap {struct plist_node node;struct ion_device *dev;enum ion_heap_type type;struct ion_heap_ops *ops;unsigned long flags;unsigned int id;const char *name;struct shrinker shrinker;struct list_head free_list;size_t free_list_size;spinlock_t free_lock;wait_queue_head_t waitqueue;struct task_struct *task;int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *);
};

ion_handle

struct ion_handle其实就是buffer,用户永健用它来表示自己的buffer,通过ion_handle_create()函数分配获得实例

1
2
3
4
5
6
7
8
struct ion_handle {struct kref ref;struct ion_client *client;struct ion_buffer *buffer;struct rb_node node;unsigned int kmap_cnt;int id;
};
  • ref成员,是struct kref结构体类型,在kernel中被广泛的用来表示引用计数,用来记录handle被引用的次数,当引用计数为0时自动销毁。
  • client成员,指向这个handle所属的client
  • buffer成员,指向真正的buffer

ion_buffer

这个结构体很重要,通过ION分配的内存就是通过它表示的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct ion_buffer {struct kref ref;...struct ion_device *dev;struct ion_heap *heap;unsigned long flags;unsigned long private_flags;size_t size;union {void *priv_virt;ion_phys_addr_t priv_phys;};struct mutex lock;int kmap_cnt;void *vaddr;int dmap_cnt;struct sg_table *sg_table;struct page **pages;struct list_head vmas;struct list_head iovas;...
};
  • ref成员,是struct kref结构体实例,维护了本 ion_buffer 的引用计数。当引用计数为 0 时会释放该 buffer,即struct ion_heap_ops::free会被调用。分配用 ION_IOC_ALLOC 型 ioctl 系统调用,相应的释放用 ION_IOC_FREE 型 ioctl 系统调用。
  • size 成员,当然是本 buffer 所表示的空间的大小,用字节表示。
  • priv_virt 成员,是所分配内存的虚拟地址啦,它常与 struct sg_table,或者封装它的结构,有关。它不是我们在内核中读写时所需的内核虚拟地址啦,内核虚拟地址使用 vaddr 成员来表示的。一般而言,物理内存不连续的,使用本字段;否则使用下面的 priv_phys 字段,如 struct ion_heap_ops contig_heap_ops
  • priv_phys 成员,表示所分配的内存的物理地址。它适用于分配的物理内存是连续的 ion heap。这种连续的物理内存:在将其映射到用户空间时,即获取用户空间虚拟地址,可以使用 remap_pfn_range() [memory.c] 这个方便的接口;在将其映射到内核空间时,即获取内核虚拟地址,可以使用 vmap() [vmalloc.c] 这个方便的接口。例子详见 struct ion_heap_ops contig_heap_ops [exynos_ion.c]。priv_virt 成员和 priv_phys 成员组成了一个联合体,其实都表示地址,只不过不同的场景下具体用的不一样而已。
  • kmap_cnt 成员,记录本 buffer 被映射到内核空间的次数。
  • vaddr 成员,是本 buffer 对应的内核虚拟地址。当 kmap_cnt 不为 0 时有效。可以通过 ion_map_kernel() [ion.c] 来获取本 buffer 对应的内核虚拟地址。ion_map_kernel()[ion.c] 实际上调用的是相应 struct ion_heap_ops::map_kernel 回调函数获取相应的虚拟地址的。
  • dmap_cnt 成员,记录本 buffer 被 mapped for DMA 的次数。
  • sg_table 成员,是 struct sg_table 结构体类型的指针。本字段与 DMA 操作有关,而且仅仅在 dmap_cnt 成员变量不为 0 时是有效的。可以通过 ion_buffer_create() [ion.c] 来初始化本成员变量,该函数实际上是调用相应 ion_heap 所属的 struct ion_heap_ops::map_dma 回调函数获取本字段的值的。
  • dirty 成员,表示 bitmask。即以位图表示本 buffer 的哪一个 page 是 dirty 的,即不能直接用于 DMA。dirty 表示 DMA 的不一致性,即 CPU 缓存中的内容与内存中的实际内容不一样。

用一张图来展示这些数据结构之间的基本关系。后面一起来看看如何在用户空间和内核空间来使用ION 共享内存机制。

您的赞赏是对我最大的肯定

Android ION 内存管理相关推荐

  1. android之ION内存管理器(1)-- 简介

    by JHJ(jianghuijun211@gmail.com) 为什么需要ION 回顾2011年末[2],LWN审查了android kernel patch[3],以期望将这些patch合并到ke ...

  2. Linux下ion内存,ION内存管理剖析.doc

    1.android之ION内存管理器(1)-- 简介 为什么需要ION 2011年末[2],LWN审查了android kernel patch[3],以期望将这些patch合并到kernel主线中. ...

  3. Android之内存管理-内存监测-内存优化

    推荐文章:Android进程与内存及内存泄漏 Android之内存管理 1.1 Dalvik Dalvik虚拟机是Android程序的虚拟机,是Android中Java程序的运行基础.其指令集基于寄存 ...

  4. Android 之 内存管理

    概述 在android的开发中,要时刻主要内存的分配和垃圾回收,因为系统为每一个dalvik虚拟机分配的内存是有限的,在google的G1中,分配的最大堆大小只有16M,后来的机器一般都为24M,实在 ...

  5. Android手机内存管理与性能优化

    Android手机内存管理与性能优化&JNI.NDK高级编程(JNI.Dalvik.内存监测) 课程分类:Android 适合人群:中级 课时数量:34小节课时 用到技术:Dalvik,DDM ...

  6. Android之ION内存管理分析

    备注:图片中的双向箭头表示他们是链表,前后链接起来的,单向箭头表示指针指向谁.     感兴趣可以加QQ群85486140,大家一起交流相互学习下! 做Camera都快2年了,对buffer流转,bu ...

  7. linux内存管理之 ION 内存管理器浅析Ⅰ(system heap)

    目录 1 什么是ION 2 ION中不同 type 的 heap 3 ION分配(以system heap为例) 3.1 ion_alloc() 3.2 ion_system_heap_allocat ...

  8. linux ion 分配地址,Android ION内存分配

    ION设计的目标 为了避免内存碎片化,或者为一些有着特殊内存需求的硬件,比如GPUs.display controller以及camera等,在系统启动的时候,会为他们预留一些memory pools ...

  9. ION内存管理器介绍

    1. ION介绍 ION是google在Android4.0为了解决内存碎片化管理而引入的通用内存管理器,用来支持不同的内存分配机制,如CARVOUT(PMEM),物理连续内存(kmalloc),虚拟 ...

最新文章

  1. 【转】使用Javascript改变HTML内容
  2. python里dir是什么意思_python中dir什么作用
  3. shipyard-----------docker容器的可视化管理
  4. linux 总数 进程_Linux运用一些常用命令,优秀的PHPer都需掌握
  5. Trie树的C++实现
  6. 六石管理学:提出分形进度的概念
  7. Qt加载gif动态图
  8. 给文字添加超链接,没有你想的那么难
  9. multisim红绿灯元器件在哪里_实验二Multisim交通灯仿真.ppt
  10. cf. ConneR and the A.R.C. Markland-N
  11. 程序猿想平稳度过35岁中年危机?不妨试着考个研
  12. easyPR车牌识别分析与测试结果
  13. 在html页面上引用脚本文件,如何在html中调用JS文件
  14. 因特网,万维网,互联网什么区别?
  15. Use After Free
  16. android的SDK、ADT下载地址
  17. Spring核心技术(十四)——ApplicationContext的额外功能
  18. SEO基础知识:什么是网站结构,为什么重要?
  19. JavaScript语言精粹--读书笔记三之replace()与正则
  20. 基于Python点餐外卖系统设计与实现 开题报告

热门文章

  1. 习题3-1至习题3-5
  2. python可视化库matplotlib_Python可视化库matplotlib(基础整理)
  3. 图像处理工具-Stirmark使用方法
  4. 远程调用:远程过程调用(RPC)和远程方法调用(RMI)
  5. 【序列建模】DIN深度兴趣网络
  6. MySQL函数(CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型)
  7. 计算机没网络本地连接接下来,电脑本地连接没有了网络连接的本地连接不见的解决方法...
  8. nginxgrafana监控面板显示nodatatoshow
  9. iOS框架介绍--EF字头
  10. 操作系统第五章 设备管理(上)笔记