Android学习之ION memory manager

Updated: 2013/03/18, 刚有时间浏览了最新的Android builder submit 2013的相关slides,其中有关于最新的android 对kernel的upstream的状态的总结,大家可以看看
http://events.linuxfoundation.org/images/stories/slides/abs2013_stultz.pdf


ION, 正在开发并准备进入staging


最近关注了一下android上kernel的一些变化,发现了一个很有意思的东西,ION.


  1. 先看一下什么是ION
    ION与PMEM类似,管理一或多个内存池,其中有一些会在boot time的时候预先分配,以备给特殊的硬件使用(GPU,显示控制器等)。它通过ION heaps来管理这些pool。
    它可以被userspace的process之间或者内核中的模块之间进行内存共享

  2. 关键数据结构
    kernel side
    用来管理内存池的相关操作的数据结构,它被ion core所使用,并没有暴露给userspace或者driver
    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); --> xxx_dma管理到dma buffer的内存映射
    	void * (*map_kernel) (struct ion_heap *heap, 
    	         struct ion_buffer *buffer);
    	void (*unmap_kernel) (struct ion_heap *heap, 
    	         struct ion_buffer *buffer); --> xxx_kernel管理到kernel的virtual address的内存映射
    	int (*map_user) (struct ion_heap *heap, struct ion_buffer *buffer,
    			 struct vm_area_struct *vma); -->管理到用户空间的内存映射
       };

    目前提供三种类型的heap
    ION_HEAP_TYPE_SYSTEM: 使用vmalloc_user()分配的heap,这个对应ion_heap_ops中的map_user函数
    ION_HEAP_TYPE_SYSTEM_CONTIG: 通过kzalloc分配的heap
    ION_HEAP_TYPE_CARVEOUT:	在启动的时候就保留的物理上连续的内存块
    可以方便的加入新的heap类型,Nvidia就实现了一个基于IOMMU的heap。

    ion.h中虽然还定义了一个ION_HEAP_TYPE_CUSTOM,但是它并没有被实现。

    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)
      


    ION通过debugfs来提供相应的调试接口

    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功能。

  4. 关于如何使用它的例子
    正在check Linaro android的实现,找到对应的使用,会再更新这里

参考资料:

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

http://lwn.net/Articles/394665/

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



你可能感兴趣的:(android,framework,driver,kernel,graphic,arm,android,manager,struct,buffer,allocation)