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/

相關文章
相關標籤/搜索