Android系列-ION内存管理简介

Android系列-ION内存管理简介

一、ION相关介绍

Android的ION子系统的目的主要是通过在硬件设备和用户空间之间分配和共享内存,实现设备之间零拷贝共享内存。说来简单,其实不易。在Soc硬件中,许多设备可以进行DMA,这些设备可能有不同的能力,以及不同的内存访问机制。

ION是Google在Android 4.0 ICS中引入,用于改善对于当前不同的android设备,有着各种不同内存管理接口管理相应内存的状况。当前存在着各种不同的但是功能却类似的内存管理接口,例如在NVIDIA Tegra有一个“NVMAP”机制、在TI OMAP有一个“CMEM”机制、在Qualcomm MSM有一个“PMEM”机制,ION将其进行通用化,通过其接口,可集中分配各类不同内存(heap),同时上述三个芯片厂商也正将其内存管理策略切换至ION上。

另外,ION在内核空间和用户空间分别有一套接口,它不仅能管理内存,还可在其clients(来自内核的或者来自用户空间的)之间共享内存。

综上,ION主要功能:

  • 内存管理器:提供通用的内存管理接口,通过heap管理各种类型的内存。
  • 共享内存:可提供驱动之间、用户进程之间、内核空间和用户空间之间的共享内存。

二、实现原理

在ION中,用不同heap代表不同类型的内存,每种heap有自己的内存分配策略。

主要的heap:

  • ION_HEAP_TYPE_SYSTEM: 使用vmalloc分配,这个对应ion_heap_ops中的map_user函数
  • ION_HEAP_TYPE_SYSTEM_CONTIG: 通过kmalloc分配
  • ION_HEAP_TYPE_CARVEOUT: 在启动的时候就保留的物理上连续的内存块
  • 另外还有两种,这里不关注:
  • ION_HEAP_TYPE_CHUNK
  • ION_HEAP_TYPE_DMA: memory allocated via DMA API
图片.png

每个heap中可分配若干个buffer,每个client通过handle管理对应的buffer。每个buffer只能有一个handle对应,每个用户进程只能有一个client,每个client可能有多个handle。两个client通过文件描述符fd(和handle有所对应,通过handle获取),通过映射方式,将相应内存映射,实现共享内存。

图片.png

三、使用方法

下面的内容着重讲述用户空间进程之间的内存共享。

1、用户空间内使用ION的方法

用户空间可以使用libion库实现对ion的操作,这里不讲述该库的操作方法,用户程序直接通过ioctl和驱动打交道,ion常见的ioctl命令为:

  • ION_IOC_ALLOC: 分配内存
  • ION_IOC_FREE: 释放内存
  • ION_IOC_MAP: 获得一个只想mmap映射的内存的文件描述符
  • ION_IOC_SHARE: 创建一个指向共享的内存的文件描述符
  • ION_IOC_IMPORT: 引入一个共享的文件描述符
  • ION_IOC_CUSTOM: 调用平台自定义的ioctl

具体使用示例可以参见该库的文件实现(system/core/lib/ion/),或如下:

sharedMemoryION.txz

(1)获取一个ION client

需要打开ION设备:

open("/dev/ion", O_RDONLY)

这里,进程要有访问权限,虽然是使用O_RDONLY标记但是也返回一个可写的内存。返回的文件描述符号做为表示一个ION client的handle。每个用户进程只能有一个client。用户空间的client通过ioctl()系统调用接口和ION交互。

(2)设置获取buffer的参数

填充结构ion_allocation_data,主要包含如下成员:

struct ion_allocation_data {
    size_t len;
    size_t align;
    unsigned int heap_mask;
    unsigned int flags;
    struct ion_handle *handle;                                                                                                                      
};

这里 handle做为输出 (struct ion_handle 类型),需要填充的是其中除handle成员之外的成员(整个buffer是 struct ion_allocation_data 类型)。对于其他参数,注意在文档 (http://lwn.net/Articles/480055/) 中并没有给出heap_mask,只说flags是一个比特掩码,标识一个或者多个将要分配所使用的ION heap(结合后面,它的解释是错误的,应该是对heap_mask的解释),但是从源代码中的注释看,这些参数的含义如下:

  • len:分配的大小。
  • align:分配所需的对其参数。
  • heap_mask:待分配所使用的所有heaps的掩码(如:ION_HEAP_SYSTEM_MASK)。
  • flags:传给heap的标志(如:ION_FLAG_CACHED),ion系统使用低16位,高16位用于各自heap实现使用。

具体各自取值和实现,请参见ion驱动头文件定义和驱动代码。

(3)分配buffer

将设置好的buffer参数传递给ioctl:

int ioctl(int client_fd, ION_IOC_ALLOC, struct ion_allocation_data *allocation_data)

这里,client_fd就是刚刚打开的/dev/ioc文件描述符号。分配的buffer通过返回的上述结构的 struct ion_handle *handle 成员来引用,但是这个handle并不是一个CPU访问的地址。一个client不能有两个handle指向同样的buffer。

(4)共享buffer

buffer的handle只能通过如下调用获取一个文件描述符号用于buffer共享:

int ioctl(int client_fd, ION_IOC_SHARE, struct ion_fd_data *fd_data);

其中fd_data如下:

struct ion_fd_data {
        struct ion_handle *handle;
        int fd;
   }

这里, handle是输入 ,标示要共享buffer的handle; fd是输出 ,标示用于共享buffer的文件描述符号。

(5)传递待共享的文件描述符号

在android设备中,可能会通过Binder机制将共享的文件描述符fd发送给另外一个进程。

为了获得被共享的buffer,第二个用户进程必须通过首先调用 open("/dev/icon", O_RDONLY) 获取一个client handle,ION通过进程ID跟踪它的用户空间clients。 在同一个进程中重复调用open("/dev/icon", O_RDONLY)将会返回另外一个文件描述符号,这个文件描述符号会引用内核同样的client结构

获取到共享文件描述符fd后,共享进程可以通过mmap来操作共享内存。

(6)释放

为了释放缓存,第二个client需要通过munmap来取消mmap的效果,第一个client需要关闭通过ION_IOC_SHARE命令获得的文件描述符号,并且使用ION_IOC_FREE如下:

int ioctl(int client_fd, ION_IOC_FREE, struct ion_handle_data *handle_data);

其中:

struct ion_handle_data {
    struct ion_handle *handle;
}

命令会导致handle的引用计数减少1。当这个引用计数达到0的时候,ion_handle对象会被析构,同时ION的索引数据结构被更新。

用户进程也可与内核驱动共享ION buffer。

2、内核空间内使用ION的方法

具体参见参考资料,这里简略介绍。

(1)获取一个ION Client

调用如下函数:

struct ion_client *ion_client_create(struct ion_device *dev,unsigned int heap_mask, const char *debug_name)

内核中可以有多个ION clients,每个使用ION的driver拥有一个client。这里,参数dev就是对应/dev/ion的设备,为何需要这个参数,目前还不确切;参数heap_mask和前面叙述一样,用于选择一个或多个ion heaps类型标识堆类型。flags参数前面说过了。

(2)共享来自用户空间的ion buffer

用户传递 ion共享文件描述符 给内核驱动,驱动 转成ion_handle

struct ion_handle *ion_import_fd(struct ion_client *client, int fd_from_user);

在许多包含多媒体中间件的智能手机中,用户进程经常从ion中分配buffer,然后使用ION_IOC_SHARE命令获取文件描述符号,然后将文件描述符号传递给内核驱动。内核驱动调用ion_import_fd()将文件描述符转换成ion_handle对象。内核驱动使用ion_handle对象做为对共享buffer的client本地引用。该函数查找buffer的物理地址一确认是否这个client是否之前分配了同样的buffer,如果是,则仅增加相应handle的引用计数。

有些硬件块只能操作物理地址连续的buffer,所以相应的驱动应 对ion_handle转换

int ion_phys(struct ion_client *client, struct ion_handle *handle, ion_phys_addr_t *addr, size_t *len)

若buffer的物理地址不连续,这个调用会失败。

在处理client的调用之时,ion始终会对input file descriptor,client,和handle arguments进行确认。例如:当import一个file descriptor(文件描述符)之时,ion会保证这个文件描述符确实是通过ION_IOC_SHARE命令创建的。当ion_phys()被调用之时,ION会验证buffer handle是否在client允许访问的handles列表中,若不是,则返回错误。这些验证机制减少了期望之外的访问与资源泄露。

四、ION 调试

关于ION debug,在 /sys/kernel/debug/ion/ 提供一个debugfs 接口。

每个heap都有自己的debugfs目录,client内存使用状况显示在 /sys/kernel/debug/ion/<<heap name>>

$cat /sys/kernel/debug/ion/ion-heap-1 
 client              pid             size
test_ion             2890            16384

每个由pid标识的client也有一个debugfs目录/sys/kernel/debug/ion/<a id="orgtarget1"></a>

$cat /sys/kernel/debug/ion/2890 
heap_name:    size_in_bytes
ion-heap-1:    40960 11

五、其它资料

待更新

内核空间

注:使用例如“git clone https://android.googlesource.com/kernel/common” 下载之后,目录为空,这可能是因为存在多个分支,而当前分支为空,可以用"git branch -a"查看相应分支,然后切换之。

用户空间

同样可参照上述方法下载。

整体介绍:

https://wiki.linaro.org/BenjaminGaignard/ion

功能方面:

http://lwn.net/Articles/565469/

使用方面:

http://lwn.net/Articles/480055/

其它参考:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343