AndroidのIONについて調べたのでメモ。
意外と日本語のサイトは少ない印象を受けたので、役立つことを期待します。
###[back ground]
・memory fragmentationの解消が目的。
・もともと、NVIDIA-NVMAP, TI-CMEM, Qualcomm-PMEMといったようにSoc Vendorが開発していたが、現在はIONへ統合されている。
###[feature]
・memory fragmentationを解消するために技術。
・ION clientで領域を共有することができる。
・デバイスに依存した領域を予約することができる。(platformに依存したconfigが可能)
・予約された領域(memory pool)が、ION HEAPと呼ばれる。
・ION HEAPによって確保された領域は、物理連続領域である。
・ユーザclientは、/dev/ionを介して(open(2)して)、ion_allocation_data情報をargにして、ioctl(2)でIONを操作する。
・ユーザ空間では、open(2)したfile descriptorをIPCなどで他processへ教えることで、ION領域をshareできる(importできる)IFにになっている。
###[source code]
/**
* enum ion_heap_types - list of all possible types of heaps
* @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc
* @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc
* @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved
* carveout heap, allocations are physically
* contiguous
* @ION_HEAP_TYPE_DMA: memory allocated via DMA API
* @ION_NUM_HEAPS: helper for iterating over heaps, a bit mask
* is used to identify the heaps, so only 32
* total heap types are supported
*/
enum ion_heap_type {
ION_HEAP_TYPE_SYSTEM,
ION_HEAP_TYPE_SYSTEM_CONTIG,
ION_HEAP_TYPE_CARVEOUT,
ION_HEAP_TYPE_CHUNK,
ION_HEAP_TYPE_DMA,
ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
are at the end of this enum */
ION_NUM_HEAPS = 16,
};
-> defaultでは、上記のpoolがあるが、追加することでユーザ独自のheapを定義可能。
例えば。
https://lists.linaro.org/pipermail/linaro-mm-sig/2012-January/001002.html
のpatchはNVIDIA独自のpoolを含んでいる。
/**
* DOC: ION_IOC_ALLOC - allocate memory
*
* Takes an ion_allocation_data struct and returns it with the handle field
* populated with the opaque handle for the allocation.
*/
#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \
struct ion_allocation_data)
/**
* DOC: ION_IOC_FREE - free memory
*
* Takes an ion_handle_data struct and frees the handle.
*/
#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
/**
* DOC: ION_IOC_MAP - get a file descriptor to mmap
*
* Takes an ion_fd_data struct with the handle field populated with a valid
* opaque handle. Returns the struct with the fd field set to a file
* descriptor open in the current address space. This file descriptor
* can then be used as an argument to mmap.
*/
#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
/**
* DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation
*
* Takes an ion_fd_data struct with the handle field populated with a valid
* opaque handle. Returns the struct with the fd field set to a file
* descriptor open in the current address space. This file descriptor
* can then be passed to another process. The corresponding opaque handle can
* be retrieved via ION_IOC_IMPORT.
*/
#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
/**
* DOC: ION_IOC_IMPORT - imports a shared file descriptor
*
* Takes an ion_fd_data struct with the fd field populated with a valid file
* descriptor obtained from ION_IOC_SHARE and returns the struct with the handle
* filed set to the corresponding opaque handle.
*/
#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
/**
* DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory
*
* Deprecated in favor of using the dma_buf api's correctly (syncing
* will happend automatically when the buffer is mapped to a device).
* If necessary should be used after touching a cached buffer from the cpu,
* this will make the buffer in memory coherent.
*/
#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
/**
* DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl
*
* Takes the argument of the architecture specific ioctl to call and
* passes appropriate userdata for that ioctl
*/
#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
-> Interfaceは上記の通り、defaultではかなりすっきりしている。
SoC Vendorが独自のIFを作成できるようになっている。
struct ion_device *ion_device_create(long (*custom_ioctl)
(struct ion_client *client,
unsigned int cmd,
unsigned long arg))
{
struct ion_device *idev;
int ret;
idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL);
if (!idev)
return ERR_PTR(-ENOMEM);
idev->dev.minor = MISC_DYNAMIC_MINOR;
idev->dev.name = "ion";
idev->dev.fops = &ion_fops;
idev->dev.parent = NULL;
ret = misc_register(&idev->dev);
if (ret) {
pr_err("ion: failed to register misc device.\n");
return ERR_PTR(ret);
}
idev->debug_root = debugfs_create_dir("ion", NULL);
if (!idev->debug_root) {
pr_err("ion: failed to create debugfs root directory.\n");
goto debugfs_done;
}
idev->heaps_debug_root = debugfs_create_dir("heaps", idev->debug_root);
if (!idev->heaps_debug_root) {
pr_err("ion: failed to create debugfs heaps directory.\n");
goto debugfs_done;
}
idev->clients_debug_root = debugfs_create_dir("clients",
idev->debug_root);
if (!idev->clients_debug_root)
pr_err("ion: failed to create debugfs clients directory.\n");
-> debugfs(/sys/kernel/debug/ion)でclientなどが確認できるようになっている。(はず。)
ion driverのdummy_init関数で実行されている。
(*) linux-4.1.2
###[referenece]
The Android ION memory allocator
###[最後に]
不明点や質問があれば、時間があれば調べるので記載お願いします。