分享

Android学习之ION memory manager

 子路问学 2013-06-28

先看一下什么是ION

ION是google在Android4.0 ICS为了解决内存碎片管理而引入的通用内存管理器,它会更加融合kernel。目前QCOM MSM, NVDIA Tegra, TI OMAP, MRVL PXA都用ION替换PMEM。

ION与PMEM类似,管理一或多个内存池,其中有一些会在boot time的时候预先分配,以备给特殊的硬件使用(GPU,显示控制器等)。

它通过ION heaps来管理这些pool。它可以被userspace的process之间或者内核中的模块之间进行内存共享

 ION 框架[1]

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

  • ION_HEAP_TYPE_SYSTEM : 通过vmalloc分配内存
  • ION_HEAP_TYPE_SYSTEM_CONTIG: 通过kmalloc分配内存
  • ION_HEAP_TYPE_CARVEOUT: 在保留内存块中(reserve memory)分配内存
  • ION_HEAP_TYPE_CUSTOM: 由客户自己定义

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

Kernel Driver间如何共享memory

kernel中使用ion_client_create来获得一个ion client的句柄,
struct ion_client *ion_client_create(struct ion_device *dev,unsigned int heap_mask, const char *debug_name)
驱动通过userspace传递来的dev(/dev/ion)来获得一个ion client, 然后调用以下函数,把fd转换成driver认识的ion_handle objects
struct ion_handle *ion_import_fd(struct ion_client *client, int fd_from_user);
如果像视频编解码硬件类似的driver需要操作物理上连续的空间,则还需要把ion_handle转换为一个物理连续的buffer
int ion_phys(struct ion_client *client, struct ion_handle *handle,ion_phys_addr_t *addr, size_t *len)

userspace side

ion通过/dev/ion设备来与用户侧的程序交互。userspace通过调用ioctl来进行内存的操作。
当获得该设备文件的描述符后,通过操作ion_allocation_data来获得所要的内存空间
struct ion_allocation_data {
size_t len;
size_t align;
unsigned int flags; -->可以制定从多种heap type来获得所要的空间,这里需要注意,指定了多个type时,分配的顺序是由boot时加载heap(ion_device_add_heap())的顺序的LIFO。
struct ion_handle *handle;
}

分配内存的ioctl
int ioctl(int client_fd, ION_IOC_ALLOC, struct ion_allocation_data *allocation_data)
请注意,userspace的操作都是基于打开的/dev/ion的文件描述符,通过它结合android中的IPC Binder来在多个process之间传递fd,来达到共享内存的目的!!
相应的共享管理,依旧采用referrence count机制。

目前总有六个ioctl cmd提供给userspace
ION_IOC_ALLOC: 分配内存
ION_IOC_FREE: 释放内存
ION_IOC_MAP: 获得一个只想mmap映射的内存的文件描述符
ION_IOC_SHARE: 创建一个指向共享的内存的文件描述符
ION_IOC_IMPORT: 引入一个共享的文件描述符
ION_IOC_CUSTOM: 调用平台自定义的ioctl
其中ION_IOC_MAP/ION_IOC_SHARE使用一套代码完成,linaro建议只使用ION_IOC_SHARE这个cmd,以便能够不用区分实际map与mmap。


3.ION与DMABUF的比较
dma_buf 与 ion_buffer类似
dma_buf_attachment与ion_handle类似
两者的主要关注的方面不同,如下图

从中可以看出,DMABUF的适用面更广可以支持更多的平台,而ION目前只支持android。ION可以支持userspace端更方便的使用(这是android driver的通性),而DMABUF只有kernel端的API,通常只对driver/kernel开发者开放接口。

目前Linaro正在努力整合CMA和ION,以期能够更好的利用ION的用户接口来利用DMABUF的DMA Mapping功能。


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多