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

为何须要ION

回顾2011年底[2],LWN审查了 android kernel patch[3],以指望将这些patch合并到kernel主线中。可是PMEM(android实现的 一个内存分配器)使这个愿望破灭了。为何PMEM不被linux 社区接受的缘由在[3]中有讲到。从那开始,PMEM很明确会被彻底抛弃,取而代之的是ION内存管理器。ION是google在Android4.0 ICS为了解决内存碎片管理而引入的通用内存管理器,它会更加融合kernel。目前QCOM MSM, NVDIA Tegra, TI OMAP, MRVL PXA都用ION替换PMEM。linux

 如何获取source code

http://android.googlesource.com/kernel/common.gitandroid

ION codes reside in drivers/gpu/iongit

Specific usage examples on omap4:app

http://android.googlesource.com/kernel/omap.git框架

 ION 框架[1]

ION 定义了四种不一样的heap,实现不一样的内存分配策略。ide

  • ION_HEAP_TYPE_SYSTEM : 经过vmalloc分配内存函数

  • ION_HEAP_TYPE_SYSTEM_CONTIG: 经过kmalloc分配内存google

  • ION_HEAP_TYPE_CARVEOUT: 在保留内存块中(reserve memory)分配内存spa

  • ION_HEAP_TYPE_CUSTOM: 由客户本身定义.net

 

下图是两个client共享内存的示意图。图中有2个heap(每种heap都有本身的内存分配策略),每一个heap中分配了若干个buffer。client的handle管理到对应的buffer。两个client是经过文件描述符fd来实现内存共享的。

ION APIs

用户空间 API

定义了6种 ioctl 接口,能够与用户应用程序交互。

  • ION_IOC_ALLOC: 分配内存

  • ION_IOC_FREE: 释放内存

  • ION_IOC_MAP: 获取文件描述符进行mmap  (? 在code中未使用这个定义)

  • ION_IOC_SHARE: 建立文件描述符来实现共享内存

  • ION_IOC_IMPORT: 获取文件描述符

  • ION_IOC_CUSTOM: 调用用户自定义的ioctl

ION_IOC_SHARE 及ION_IOC_IMPORT是基于DMABUF实现的,因此当共享进程获取文件描述符后,能够直接调用mmap来操做共享内存。mmap实现由DMABUF子系统调用ION子系统中mmap回调函数完成。

内核空间 API

内核驱动也能够注册为一个ION的客户端(client),能够选择使用哪一种类型的heap来申请内存。

  • ion_client_create: 分配一个客户端。

  • ion_client_destroy: 释放一个客户端及绑定在它上面的全部ion handle.

ion handle: 这里每一个ion handle映射到一个buffer中,每一个buffer关联一个heap。也就是说一个客户端能够操做多块buffer。

Buffer 申请及释放函数:

  • ion_alloc: 申请ion内存,返回ion handle

  • ion_free: 释放ion handle

ION 经过handle来管理buffer,驱动须要能够访问到buffer的地址。ION经过下面的函数来达到这个目的

  • ion_phys: 返回buffer的物理地址(address)及大小(size)

  • ion_map_kernel: 给指定的buffer建立内核内存映射

  • ion_unmap_kernel: 销毁指定buffer的内核内存映射

  • ion_map_dma: 为指定buffer建立dma 映射,返回sglist(scatter/gather list)

  • ion_unmap_dma: 销毁指定buffer的dma映射

ION是经过handle而非buffer地址来实现驱动间共享内存,用户空间共享内存也是利用一样原理。

  • ion_share: given a handle, obtain a buffer to pass to other clients

  • ion_import: given an buffer in another client, import it

  • ion_import_fd: given an fd obtained via ION_IOC_SHARE ioctl, import it

Heap API

Heap 接口定义 [drivers/gpu/ion/ion_priv.h]

这些接口不是暴露给驱动或者用户应用程序的。

/**
 * struct ion_heap_ops - ops to operate on a given heap
 * @allocate:           allocate memory
 * @free:               free memory
 * @phys                get physical address of a buffer (only define on physically contiguous heaps)
 * @map_dma             map the memory for dma to a scatterlist
 * @unmap_dma           unmap the memory for dma
 * @map_kernel          map memory to the kernel
 * @unmap_kernel        unmap memory to the kernel
 * @map_user            map memory to userspace
 */
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 scatterlist *(*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);
};

ION debug

ION 在/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/<<pid>>

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

 

参考文献

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

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

3. http://lwn.net/Articles/472984/

相关文章
相关标签/搜索