ION Memory Control
Overview
ION子系统目的主要是通过在硬件设备和用户空间之间分配和共享内存,实现设备之间零拷贝共享内存。
零拷贝:CPU不执行拷贝数据从一个存储区域到另一个存储区域
ION是Google在Android 4.0 ICS中引入,用于改善对于当前不同平台的android设备,使用各种不同内存管理接口来管理相应内存的状况,ION将内存管理机制抽象成一系列通用的接口,可集中分配各类不同内存(ion_heap_type区分)。
ION的主要功能:
内存管理:提供通用(平台无关)的内存管理接口,通过heap管理各种类型的内存。
共享内存:可提供驱动之间、用户进程之间、内核空间和用户空间之间的共享内存。
ION 内存类型
ION通过heap类型来代表不同的内存,不同的内存有不同的分配方式。
// in ./src/system/core/libion/kernel-headers/linux/ion.h
enum ion_heap_type {
ION_HEAP_TYPE_SYSTEM,
ION_HEAP_TYPE_SYSTEM_CONTIG,
ION_HEAP_TYPE_CARVEOUT,
ION_HEAP_TYPE_CHUNK,
ION_HEAP_TYPE_DMA,
ION_HEAP_TYPE_CUSTOM,
ION_NUM_HEAPS = 16,
};每个heap中可分配若干个buffer,每个client(ion_open()返回的fd)通过handle管理对应的buffer。每个buffer只能有一个handle对应,每个用户进程只能有一个client,每个client可能有多个handle(申请多块内存空间)。两个client通过文件描述符fd,通过映射方式,将相应内存映射,实现共享内存。

handle通过ion_alloc_fd()赋值,client通过handle来获取分配的ion内存的地址,目前来说并没有碰到过使用ION共享内存的情况,可能因为效率太低?有因为要使用C2D而去申请ion buffer的情况,除了因为C2D要求使用ion,还有为了减少I/O操作加速对图片读写速度的考量,因为通过ION_IOCRL_XXX申请到的空间都位于高速缓存中,CPU可以直接读取到,并且在用户进程中为了方便使用,通常会使用mmap()将ion buffer地址映射到用户空间。
用户空间API
用户空间API通过ioctl直接与驱动交互。
ioctl()
用户空间API对应的ioctl()操作
具体的实现在ion-ioctl.c中。
ion_alloc_fd()
ion_alloc_fd()所有的参数实际是调用ion_alloc(),填充ion_allocation_data结构体,并调用对应的ioctl(ION_IOC_ALLOC)操作,并返回一个handle给handle_fd。
len:分配的大小。
align:对齐标志,通常为页对齐(4096)
heap_mask:待分配所使用的所有heaps的掩码(用于区分heap类型,实际是1 << ion_heap_type)
flags:传给heap的标志(如:ION_FLAG_CACHED),ion系统使用低16位,高16位用于各自heap实现使用。
handle:ion buffer的句柄
原以为handle会作为ion_alloc_fd()的返回,但是查看ion_share()的源码,在ion_share()中会填充ion_fd_data结构体——进程共享内存所需的元数据,并且最终返回的是用于共享内存的文件描述符。
后记
关于ION的概念就讲这么多,主要集中在应用上,再往下的内核空间API由于本人水平有限,涉及到更底层偏向于物理硬件的内存申请操作即使看过代码也无法能很好的描述其逻辑,而简单的讲解源码在我看来是没有必要的。
第一次运用ION是在多路视频应用中,使用了FFmpeg来解码视频,由于解码出的图片帧是YUV420 NV12,为了显示还需要进行色彩空间转换,如果使用常规色彩空间转换API(如OpenCV),那么会耗费大量时间在读写和拷贝操作上,因此使用C2D库(依赖于ION)来完成色彩转换操作。在当时我以为ION是一块特殊设计(具有硬件加速功能)且实际存在的物理内存(类似于主存的边角料,但被保留),因此我理解的是我的用户进程和该物理硬件之间存在内存共享。但是review代码之后,根据我的粗浅理解,这并不会用到ION内存共享的特性,只是因为ION申请到的buffer已经位于高速缓存中,提高了读写命中率,忙完手上这个AIDemo工程后会开始Camera相关的学习,也正是ION框架的应用所在,希望之后会有更好的理解。
Last updated
Was this helpful?