天天看點

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。
    Android學習之ION memory manager
  3. ION與DMABUF的比較

    dma_buf 與 ion_buffer類似

    dma_buf_attachment與ion_handle類似

    兩者的主要關注的方面不同,如下圖

    Android學習之ION memory manager

    從中可以看出,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

繼續閱讀