android記憶體管理-ION/PMEM【轉】

  • 2019 年 10 月 10 日
  • 筆記

轉自:https://www.jianshu.com/p/0eac3d3ff6bb

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

為什麼需要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。

如何獲取source code

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

ION codes reside in drivers/gpu/ion

Specific usage examples on omap4:

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

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: 由客戶自己定義

image

下圖是兩個client共享記憶體的示意圖。圖中有2個heap(每種heap都有自己的記憶體分配策略),每個heap中分配了若干個buffer。client的handle管理到對應的buffer。兩個client是通過文件描述符fd來實現記憶體共享的。

image

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