ION基本概念介绍
2013-08-13 16:34
288 查看
chipset: MSM8X25Q
codebase: Android 4.1
ION概念:
ION是Google的下一代内存管理器,用来支持不同的内存分配机制,如CARVOUT(PMEM),物理连续内存(kmalloc), 虚拟地址连续但物理不连续内存(vmalloc), IOMMU等。
用户空间和内核空间都可以使用ION,用户空间是通过/dev/ion来创建client的。
说到client, 顺便看下ION相关比较重要的几个概念。
Heap: 用来表示内存分配的相关信息,包括id, type, name等。用struct ion_heap表示。
Client: Ion的使用者,用户空间和内核控件要使用ION的buffer,必须先创建一个client,一个client可以有多个buffer,用struct ion_buffer表示。
Handle: 将buffer该抽象出来,可以认为ION用handle来管理buffer,一般用户直接拿到的是handle,而不是buffer。 用struct ion_handle表示。
heap类型:
由于ION可以使用多种memory分配机制,例如物理连续和不连续的,所以ION使用enum ion_heap_type表示。
[html]
view plaincopyprint?
/**
* 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_IOMMU: IOMMU memory
* @ION_HEAP_TYPE_CP: memory allocated from a prereserved
* carveout heap, allocations are physically
* contiguous. Used for content protection.
* @ION_HEAP_TYPE_DMA: memory allocated via DMA API
* @ION_HEAP_END: helper for iterating over heaps
*/
enum ion_heap_type {
ION_HEAP_TYPE_SYSTEM,
ION_HEAP_TYPE_SYSTEM_CONTIG,
ION_HEAP_TYPE_CARVEOUT,
ION_HEAP_TYPE_IOMMU,
ION_HEAP_TYPE_CP,
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,
};
代码中的注释很明确地说明了哪种type对应的是分配哪种memory。不同type的heap需要不同的method去分配,不过都是用struction_heap_ops来表示的。如以下例子:
[html]
view plaincopyprint?
static struct ion_heap_ops carveout_heap_ops = {
.allocate = ion_carveout_heap_allocate,
.free = ion_carveout_heap_free,
.phys = ion_carveout_heap_phys,
.map_user =
ion_carveout_heap_map_user,
.map_kernel = ion_carveout_heap_map_kernel,
.unmap_user =
ion_carveout_heap_unmap_user,
.unmap_kernel = ion_carveout_heap_unmap_kernel,
.map_dma =
ion_carveout_heap_map_dma,
.unmap_dma = ion_carveout_heap_unmap_dma,
.cache_op =
ion_carveout_cache_ops,
.print_debug = ion_carveout_print_debug,
.map_iommu =
ion_carveout_heap_map_iommu,
.unmap_iommu = ion_carveout_heap_unmap_iommu,
};
static struct ion_heap_ops kmalloc_ops = {
.allocate = ion_system_contig_heap_allocate,
.free = ion_system_contig_heap_free,
.phys = ion_system_contig_heap_phys,
.map_dma =
ion_system_contig_heap_map_dma,
.unmap_dma = ion_system_heap_unmap_dma,
.map_kernel =
ion_system_heap_map_kernel,
.unmap_kernel = ion_system_heap_unmap_kernel,
.map_user =
ion_system_contig_heap_map_user,
.cache_op = ion_system_contig_heap_cache_ops,
.print_debug =
ion_system_contig_print_debug,
.map_iommu = ion_system_contig_heap_map_iommu,
.unmap_iommu =
ion_system_heap_unmap_iommu,
};
Heap ID:
同一种type的heap上当然可以分为若该干个chunk供用户使用,所以ION又使用ID来区分了。例如在type为ION_HEAP_TYPE_CARVEOUT的heap上,audio和display部分都需要使用,ION就用ID来区分。
Heap id用enumion_heap_ids表示。
[html]
view plaincopyprint?
/**
* These are the only ids that should be used for Ion heap ids.
* The ids listed are the order in which allocation will be attempted
* if specified. Don't swap the order of heap ids unless you know what
* you are doing!
* Id's are spaced by purpose to allow new Id's to be inserted in-between (for
* possible fallbacks)
*/
enum ion_heap_ids {
INVALID_HEAP_ID = -1,
ION_CP_MM_HEAP_ID = 8,
ION_CP_MFC_HEAP_ID =
12,
ION_CP_WB_HEAP_ID = 16, /* 8660 only */
ION_CAMERA_HEAP_ID =
20, /* 8660 only */
ION_SF_HEAP_ID = 24,
ION_IOMMU_HEAP_ID =
25,
ION_QSECOM_HEAP_ID = 26,
ION_AUDIO_HEAP_BL_ID =
27,
ION_AUDIO_HEAP_ID = 28,
ION_MM_FIRMWARE_HEAP_ID =
29,
ION_SYSTEM_HEAP_ID =
30,
ION_HEAP_ID_RESERVED =
31 /** Bit reserved for ION_SECURE flag */
};
Heap 定义:
了解了heaptype和id,看看如何被用到了,本平台使用的文件为board-qrd7627a.c,有如下定义:
[html]
view plaincopyprint?
/**
* These heaps are listed in the order they will be allocated.
* Don't swap the order unless you know what you are doing!
*/
struct ion_platform_heap msm7627a_heaps[] = {
{
.id =
ION_SYSTEM_HEAP_ID,
.type = ION_HEAP_TYPE_SYSTEM,
.name =
ION_VMALLOC_HEAP_NAME,
},
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
/* PMEM_ADSP = CAMERA */
{
.id = ION_CAMERA_HEAP_ID,
.type =
CAMERA_HEAP_TYPE,
.name = ION_CAMERA_HEAP_NAME,
.memory_type =
ION_EBI_TYPE,
.extra_data = (void *)&co_mm_ion_pdata,
.priv = (void *)&ion_cma_device.dev,
},
/* AUDIO HEAP 1*/
{
.id =
ION_AUDIO_HEAP_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name =
ION_AUDIO_HEAP_NAME,
.memory_type =
ION_EBI_TYPE,
.extra_data = (void *)&co_ion_pdata,
},
/* PMEM_MDP =
SF */
{
.id =
ION_SF_HEAP_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name =
ION_SF_HEAP_NAME,
.memory_type =
ION_EBI_TYPE,
.extra_data = (void *)&co_ion_pdata,
},
/* AUDIO HEAP 2*/
{
.id =
ION_AUDIO_HEAP_BL_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name =
ION_AUDIO_BL_HEAP_NAME,
.memory_type =
ION_EBI_TYPE,
.extra_data = (void *)&co_ion_pdata,
.base = BOOTLOADER_BASE_ADDR,
},
#endif
};
ION Handle:
当Ion client分配buffer时,相应的一个唯一的handle也会被指定,当然client可以多次申请ion buffer。申请好buffer之后,返回的是一个ion handle, 不过要知道Ion buffer才和实际的内存相关,包括size, address等信息。Struct ion_handle和struct ion_buffer如下:
[html]
view plaincopyprint?
/**
* ion_handle - a client local reference to a buffer
* @ref: reference count
* @client: back pointer to the client the buffer resides in
* @buffer: pointer to the buffer
* @node: node in the client's handle rbtree
* @kmap_cnt: count of times this client has mapped to kernel
* @dmap_cnt: count of times this client has mapped for dma
*
* Modifications to node, map_cnt or mapping should be protected by the
* lock in the client. Other fields are never changed after initialization.
*/
struct ion_handle {
struct kref ref;
struct ion_client *client;
struct ion_buffer *buffer;
struct rb_node node;
unsigned int kmap_cnt;
unsigned int iommu_map_cnt;
};
/**
* struct ion_buffer - metadata for a particular buffer
* @ref: refernce count
* @node: node in the ion_device buffers tree
* @dev: back pointer to the ion_device
* @heap: back pointer to the heap the buffer came from
* @flags: buffer specific flags
* @size: size of the buffer
* @priv_virt: private data to the buffer representable as
* a void *
* @priv_phys: private data to the buffer representable as
* an ion_phys_addr_t (and someday a phys_addr_t)
* @lock: protects the buffers cnt fields
* @kmap_cnt: number of times the buffer is mapped to the kernel
* @vaddr: the kenrel mapping if kmap_cnt is not zero
* @dmap_cnt: number of times the buffer is mapped for dma
* @sg_table: the sg table for the buffer if dmap_cnt is not zero
*/
struct ion_buffer {
struct kref ref;
struct rb_node node;
struct ion_device *dev;
struct ion_heap *heap;
unsigned long flags;
size_t size;
union {
void *priv_virt;
ion_phys_addr_t priv_phys;
};
struct mutex lock;
int kmap_cnt;
void *vaddr;
int dmap_cnt;
struct sg_table *sg_table;
int umap_cnt;
unsigned int iommu_map_cnt;
struct rb_root iommu_maps;
int marked;
};
ION Client:
用户空间和内核空间都可以成为client,不过创建的方法稍稍有点区别,先了解下基本的操作流程吧。
内核空间:
先创建client:
[html]
view plaincopyprint?
struct ion_client *ion_client_create(struct ion_device *dev,
unsigned int heap_mask,
const char *name)
heap_mask: 可以分配的heap type,如carveout,system heap, iommu等。
高通使用msm_ion_client_create函数封装了下。
有了client之后就可以分配内存:
[html]
view plaincopyprint?
struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
size_t align, unsigned int flags)
flags: 分配的heap id.
有了handle也就是buffer之后就准备使用了,不过还是物理地址,需要map:
[html]
view plaincopyprint?
void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle,
unsigned long flags)
用户空间:
用户空间如果想使用ION,也必须先要创建client,不过它是打开/dev/ion,实际上它最终也会调用ion_client_create。
不过和内核空间创建client的一点区别是,用户空间不能选择heap type,但是内核空间却可以。
另外,用户空间是通过IOCTL来分配内存的,cmd为ION_IOC_ALLOC.
[html]
view plaincopyprint?
ion_fd = open("/dev/ion", O_ RDONLY | O_SYNC);
ioctl(ion_fd, ION_IOC_ALLOC, alloc);
alloc为struct ion_allocation_data,len是申请buffer的长度,flags是heap id。
[html]
view plaincopyprint?
/**
* struct ion_allocation_data - metadata passed from userspace for allocations
* @len: size of the allocation
* @align: required alignment of the allocation
* @flags: flags passed to heap
* @handle: pointer that will be populated with a cookie to use to refer
* to this allocation
*
* Provided by userspace as an argument to the ioctl
*/
struct ion_allocation_data {
size_t len;
size_t align;
unsigned int flags;
struct ion_handle *handle;
};
分配好了buffer之后,如果用户空间想使用buffer,先需要mmap. ION是通过先调用IOCTL中的ION_IOC_SHARE/ION_IOC_MAP来得到可以mmap的fd,然后再执行mmap得到bufferaddress.
然后,你也可以将此fd传给另一个进程,如通过binder传递。在另一个进程中通过ION_IOC_IMPORT这个IOCTL来得到这块共享buffer了。
来看一个例子:
[html]
view plaincopyprint?
进程A:
int ionfd = open("/dev/ion", O_RDONLY | O_DSYNC);
alloc_data.len =
0x1000;
alloc_data.align = 0x1000;
alloc_data.flags =
ION_HEAP(ION_CP_MM_HEAP_ID);
rc = ioctl(ionfd,ION_IOC_ALLOC, &alloc_data);
fd_data.handle =
alloc_data.handle;
rc = ioctl(ionfd,ION_IOC_SHARE,&fd_data);
shared_fd = fd_data.fd;
进程B:
fd_data.fd = shared_fd;
rc = ioctl(ionfd,ION_IOC_IMPORT,&fd_data);
2013/02/18
codebase: Android 4.1
ION概念:
ION是Google的下一代内存管理器,用来支持不同的内存分配机制,如CARVOUT(PMEM),物理连续内存(kmalloc), 虚拟地址连续但物理不连续内存(vmalloc), IOMMU等。
用户空间和内核空间都可以使用ION,用户空间是通过/dev/ion来创建client的。
说到client, 顺便看下ION相关比较重要的几个概念。
Heap: 用来表示内存分配的相关信息,包括id, type, name等。用struct ion_heap表示。
Client: Ion的使用者,用户空间和内核控件要使用ION的buffer,必须先创建一个client,一个client可以有多个buffer,用struct ion_buffer表示。
Handle: 将buffer该抽象出来,可以认为ION用handle来管理buffer,一般用户直接拿到的是handle,而不是buffer。 用struct ion_handle表示。
heap类型:
由于ION可以使用多种memory分配机制,例如物理连续和不连续的,所以ION使用enum ion_heap_type表示。
[html]
view plaincopyprint?
/**
* 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_IOMMU: IOMMU memory
* @ION_HEAP_TYPE_CP: memory allocated from a prereserved
* carveout heap, allocations are physically
* contiguous. Used for content protection.
* @ION_HEAP_TYPE_DMA: memory allocated via DMA API
* @ION_HEAP_END: helper for iterating over heaps
*/
enum ion_heap_type {
ION_HEAP_TYPE_SYSTEM,
ION_HEAP_TYPE_SYSTEM_CONTIG,
ION_HEAP_TYPE_CARVEOUT,
ION_HEAP_TYPE_IOMMU,
ION_HEAP_TYPE_CP,
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,
};
/** * 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_IOMMU: IOMMU memory * @ION_HEAP_TYPE_CP: memory allocated from a prereserved * carveout heap, allocations are physically * contiguous. Used for content protection. * @ION_HEAP_TYPE_DMA: memory allocated via DMA API * @ION_HEAP_END: helper for iterating over heaps */ enum ion_heap_type { ION_HEAP_TYPE_SYSTEM, ION_HEAP_TYPE_SYSTEM_CONTIG, ION_HEAP_TYPE_CARVEOUT, ION_HEAP_TYPE_IOMMU, ION_HEAP_TYPE_CP, 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, };
代码中的注释很明确地说明了哪种type对应的是分配哪种memory。不同type的heap需要不同的method去分配,不过都是用struction_heap_ops来表示的。如以下例子:
[html]
view plaincopyprint?
static struct ion_heap_ops carveout_heap_ops = {
.allocate = ion_carveout_heap_allocate,
.free = ion_carveout_heap_free,
.phys = ion_carveout_heap_phys,
.map_user =
ion_carveout_heap_map_user,
.map_kernel = ion_carveout_heap_map_kernel,
.unmap_user =
ion_carveout_heap_unmap_user,
.unmap_kernel = ion_carveout_heap_unmap_kernel,
.map_dma =
ion_carveout_heap_map_dma,
.unmap_dma = ion_carveout_heap_unmap_dma,
.cache_op =
ion_carveout_cache_ops,
.print_debug = ion_carveout_print_debug,
.map_iommu =
ion_carveout_heap_map_iommu,
.unmap_iommu = ion_carveout_heap_unmap_iommu,
};
static struct ion_heap_ops kmalloc_ops = {
.allocate = ion_system_contig_heap_allocate,
.free = ion_system_contig_heap_free,
.phys = ion_system_contig_heap_phys,
.map_dma =
ion_system_contig_heap_map_dma,
.unmap_dma = ion_system_heap_unmap_dma,
.map_kernel =
ion_system_heap_map_kernel,
.unmap_kernel = ion_system_heap_unmap_kernel,
.map_user =
ion_system_contig_heap_map_user,
.cache_op = ion_system_contig_heap_cache_ops,
.print_debug =
ion_system_contig_print_debug,
.map_iommu = ion_system_contig_heap_map_iommu,
.unmap_iommu =
ion_system_heap_unmap_iommu,
};
static struct ion_heap_ops carveout_heap_ops = { .allocate = ion_carveout_heap_allocate, .free = ion_carveout_heap_free, .phys = ion_carveout_heap_phys, .map_user = ion_carveout_heap_map_user, .map_kernel = ion_carveout_heap_map_kernel, .unmap_user = ion_carveout_heap_unmap_user, .unmap_kernel = ion_carveout_heap_unmap_kernel, .map_dma = ion_carveout_heap_map_dma, .unmap_dma = ion_carveout_heap_unmap_dma, .cache_op = ion_carveout_cache_ops, .print_debug = ion_carveout_print_debug, .map_iommu = ion_carveout_heap_map_iommu, .unmap_iommu = ion_carveout_heap_unmap_iommu, }; static struct ion_heap_ops kmalloc_ops = { .allocate = ion_system_contig_heap_allocate, .free = ion_system_contig_heap_free, .phys = ion_system_contig_heap_phys, .map_dma = ion_system_contig_heap_map_dma, .unmap_dma = ion_system_heap_unmap_dma, .map_kernel = ion_system_heap_map_kernel, .unmap_kernel = ion_system_heap_unmap_kernel, .map_user = ion_system_contig_heap_map_user, .cache_op = ion_system_contig_heap_cache_ops, .print_debug = ion_system_contig_print_debug, .map_iommu = ion_system_contig_heap_map_iommu, .unmap_iommu = ion_system_heap_unmap_iommu, };
Heap ID:
同一种type的heap上当然可以分为若该干个chunk供用户使用,所以ION又使用ID来区分了。例如在type为ION_HEAP_TYPE_CARVEOUT的heap上,audio和display部分都需要使用,ION就用ID来区分。
Heap id用enumion_heap_ids表示。
[html]
view plaincopyprint?
/**
* These are the only ids that should be used for Ion heap ids.
* The ids listed are the order in which allocation will be attempted
* if specified. Don't swap the order of heap ids unless you know what
* you are doing!
* Id's are spaced by purpose to allow new Id's to be inserted in-between (for
* possible fallbacks)
*/
enum ion_heap_ids {
INVALID_HEAP_ID = -1,
ION_CP_MM_HEAP_ID = 8,
ION_CP_MFC_HEAP_ID =
12,
ION_CP_WB_HEAP_ID = 16, /* 8660 only */
ION_CAMERA_HEAP_ID =
20, /* 8660 only */
ION_SF_HEAP_ID = 24,
ION_IOMMU_HEAP_ID =
25,
ION_QSECOM_HEAP_ID = 26,
ION_AUDIO_HEAP_BL_ID =
27,
ION_AUDIO_HEAP_ID = 28,
ION_MM_FIRMWARE_HEAP_ID =
29,
ION_SYSTEM_HEAP_ID =
30,
ION_HEAP_ID_RESERVED =
31 /** Bit reserved for ION_SECURE flag */
};
/** * These are the only ids that should be used for Ion heap ids. * The ids listed are the order in which allocation will be attempted * if specified. Don't swap the order of heap ids unless you know what * you are doing! * Id's are spaced by purpose to allow new Id's to be inserted in-between (for * possible fallbacks) */ enum ion_heap_ids { INVALID_HEAP_ID = -1, ION_CP_MM_HEAP_ID = 8, ION_CP_MFC_HEAP_ID = 12, ION_CP_WB_HEAP_ID = 16, /* 8660 only */ ION_CAMERA_HEAP_ID = 20, /* 8660 only */ ION_SF_HEAP_ID = 24, ION_IOMMU_HEAP_ID = 25, ION_QSECOM_HEAP_ID = 26, ION_AUDIO_HEAP_BL_ID = 27, ION_AUDIO_HEAP_ID = 28, ION_MM_FIRMWARE_HEAP_ID = 29, ION_SYSTEM_HEAP_ID = 30, ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_SECURE flag */ };
Heap 定义:
了解了heaptype和id,看看如何被用到了,本平台使用的文件为board-qrd7627a.c,有如下定义:
[html]
view plaincopyprint?
/**
* These heaps are listed in the order they will be allocated.
* Don't swap the order unless you know what you are doing!
*/
struct ion_platform_heap msm7627a_heaps[] = {
{
.id =
ION_SYSTEM_HEAP_ID,
.type = ION_HEAP_TYPE_SYSTEM,
.name =
ION_VMALLOC_HEAP_NAME,
},
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
/* PMEM_ADSP = CAMERA */
{
.id = ION_CAMERA_HEAP_ID,
.type =
CAMERA_HEAP_TYPE,
.name = ION_CAMERA_HEAP_NAME,
.memory_type =
ION_EBI_TYPE,
.extra_data = (void *)&co_mm_ion_pdata,
.priv = (void *)&ion_cma_device.dev,
},
/* AUDIO HEAP 1*/
{
.id =
ION_AUDIO_HEAP_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name =
ION_AUDIO_HEAP_NAME,
.memory_type =
ION_EBI_TYPE,
.extra_data = (void *)&co_ion_pdata,
},
/* PMEM_MDP =
SF */
{
.id =
ION_SF_HEAP_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name =
ION_SF_HEAP_NAME,
.memory_type =
ION_EBI_TYPE,
.extra_data = (void *)&co_ion_pdata,
},
/* AUDIO HEAP 2*/
{
.id =
ION_AUDIO_HEAP_BL_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name =
ION_AUDIO_BL_HEAP_NAME,
.memory_type =
ION_EBI_TYPE,
.extra_data = (void *)&co_ion_pdata,
.base = BOOTLOADER_BASE_ADDR,
},
#endif
};
/** * These heaps are listed in the order they will be allocated. * Don't swap the order unless you know what you are doing! */ struct ion_platform_heap msm7627a_heaps[] = { { .id = ION_SYSTEM_HEAP_ID, .type = ION_HEAP_TYPE_SYSTEM, .name = ION_VMALLOC_HEAP_NAME, }, #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION /* PMEM_ADSP = CAMERA */ { .id = ION_CAMERA_HEAP_ID, .type = CAMERA_HEAP_TYPE, .name = ION_CAMERA_HEAP_NAME, .memory_type = ION_EBI_TYPE, .extra_data = (void *)&co_mm_ion_pdata, .priv = (void *)&ion_cma_device.dev, }, /* AUDIO HEAP 1*/ { .id = ION_AUDIO_HEAP_ID, .type = ION_HEAP_TYPE_CARVEOUT, .name = ION_AUDIO_HEAP_NAME, .memory_type = ION_EBI_TYPE, .extra_data = (void *)&co_ion_pdata, }, /* PMEM_MDP = SF */ { .id = ION_SF_HEAP_ID, .type = ION_HEAP_TYPE_CARVEOUT, .name = ION_SF_HEAP_NAME, .memory_type = ION_EBI_TYPE, .extra_data = (void *)&co_ion_pdata, }, /* AUDIO HEAP 2*/ { .id = ION_AUDIO_HEAP_BL_ID, .type = ION_HEAP_TYPE_CARVEOUT, .name = ION_AUDIO_BL_HEAP_NAME, .memory_type = ION_EBI_TYPE, .extra_data = (void *)&co_ion_pdata, .base = BOOTLOADER_BASE_ADDR, }, #endif };
ION Handle:
当Ion client分配buffer时,相应的一个唯一的handle也会被指定,当然client可以多次申请ion buffer。申请好buffer之后,返回的是一个ion handle, 不过要知道Ion buffer才和实际的内存相关,包括size, address等信息。Struct ion_handle和struct ion_buffer如下:
[html]
view plaincopyprint?
/**
* ion_handle - a client local reference to a buffer
* @ref: reference count
* @client: back pointer to the client the buffer resides in
* @buffer: pointer to the buffer
* @node: node in the client's handle rbtree
* @kmap_cnt: count of times this client has mapped to kernel
* @dmap_cnt: count of times this client has mapped for dma
*
* Modifications to node, map_cnt or mapping should be protected by the
* lock in the client. Other fields are never changed after initialization.
*/
struct ion_handle {
struct kref ref;
struct ion_client *client;
struct ion_buffer *buffer;
struct rb_node node;
unsigned int kmap_cnt;
unsigned int iommu_map_cnt;
};
/**
* struct ion_buffer - metadata for a particular buffer
* @ref: refernce count
* @node: node in the ion_device buffers tree
* @dev: back pointer to the ion_device
* @heap: back pointer to the heap the buffer came from
* @flags: buffer specific flags
* @size: size of the buffer
* @priv_virt: private data to the buffer representable as
* a void *
* @priv_phys: private data to the buffer representable as
* an ion_phys_addr_t (and someday a phys_addr_t)
* @lock: protects the buffers cnt fields
* @kmap_cnt: number of times the buffer is mapped to the kernel
* @vaddr: the kenrel mapping if kmap_cnt is not zero
* @dmap_cnt: number of times the buffer is mapped for dma
* @sg_table: the sg table for the buffer if dmap_cnt is not zero
*/
struct ion_buffer {
struct kref ref;
struct rb_node node;
struct ion_device *dev;
struct ion_heap *heap;
unsigned long flags;
size_t size;
union {
void *priv_virt;
ion_phys_addr_t priv_phys;
};
struct mutex lock;
int kmap_cnt;
void *vaddr;
int dmap_cnt;
struct sg_table *sg_table;
int umap_cnt;
unsigned int iommu_map_cnt;
struct rb_root iommu_maps;
int marked;
};
/** * ion_handle - a client local reference to a buffer * @ref: reference count * @client: back pointer to the client the buffer resides in * @buffer: pointer to the buffer * @node: node in the client's handle rbtree * @kmap_cnt: count of times this client has mapped to kernel * @dmap_cnt: count of times this client has mapped for dma * * Modifications to node, map_cnt or mapping should be protected by the * lock in the client. Other fields are never changed after initialization. */ struct ion_handle { struct kref ref; struct ion_client *client; struct ion_buffer *buffer; struct rb_node node; unsigned int kmap_cnt; unsigned int iommu_map_cnt; }; /** * struct ion_buffer - metadata for a particular buffer * @ref: refernce count * @node: node in the ion_device buffers tree * @dev: back pointer to the ion_device * @heap: back pointer to the heap the buffer came from * @flags: buffer specific flags * @size: size of the buffer * @priv_virt: private data to the buffer representable as * a void * * @priv_phys: private data to the buffer representable as * an ion_phys_addr_t (and someday a phys_addr_t) * @lock: protects the buffers cnt fields * @kmap_cnt: number of times the buffer is mapped to the kernel * @vaddr: the kenrel mapping if kmap_cnt is not zero * @dmap_cnt: number of times the buffer is mapped for dma * @sg_table: the sg table for the buffer if dmap_cnt is not zero */ struct ion_buffer { struct kref ref; struct rb_node node; struct ion_device *dev; struct ion_heap *heap; unsigned long flags; size_t size; union { void *priv_virt; ion_phys_addr_t priv_phys; }; struct mutex lock; int kmap_cnt; void *vaddr; int dmap_cnt; struct sg_table *sg_table; int umap_cnt; unsigned int iommu_map_cnt; struct rb_root iommu_maps; int marked; };
ION Client:
用户空间和内核空间都可以成为client,不过创建的方法稍稍有点区别,先了解下基本的操作流程吧。
内核空间:
先创建client:
[html]
view plaincopyprint?
struct ion_client *ion_client_create(struct ion_device *dev,
unsigned int heap_mask,
const char *name)
struct ion_client *ion_client_create(struct ion_device *dev, unsigned int heap_mask, const char *name)
heap_mask: 可以分配的heap type,如carveout,system heap, iommu等。
高通使用msm_ion_client_create函数封装了下。
有了client之后就可以分配内存:
[html]
view plaincopyprint?
struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
size_t align, unsigned int flags)
struct ion_handle *ion_alloc(struct ion_client *client, size_t len, size_t align, unsigned int flags)
flags: 分配的heap id.
有了handle也就是buffer之后就准备使用了,不过还是物理地址,需要map:
[html]
view plaincopyprint?
void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle,
unsigned long flags)
void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle, unsigned long flags)
用户空间:
用户空间如果想使用ION,也必须先要创建client,不过它是打开/dev/ion,实际上它最终也会调用ion_client_create。
不过和内核空间创建client的一点区别是,用户空间不能选择heap type,但是内核空间却可以。
另外,用户空间是通过IOCTL来分配内存的,cmd为ION_IOC_ALLOC.
[html]
view plaincopyprint?
ion_fd = open("/dev/ion", O_ RDONLY | O_SYNC);
ioctl(ion_fd, ION_IOC_ALLOC, alloc);
ion_fd = open("/dev/ion", O_ RDONLY | O_SYNC); ioctl(ion_fd, ION_IOC_ALLOC, alloc);
alloc为struct ion_allocation_data,len是申请buffer的长度,flags是heap id。
[html]
view plaincopyprint?
/**
* struct ion_allocation_data - metadata passed from userspace for allocations
* @len: size of the allocation
* @align: required alignment of the allocation
* @flags: flags passed to heap
* @handle: pointer that will be populated with a cookie to use to refer
* to this allocation
*
* Provided by userspace as an argument to the ioctl
*/
struct ion_allocation_data {
size_t len;
size_t align;
unsigned int flags;
struct ion_handle *handle;
};
/** * struct ion_allocation_data - metadata passed from userspace for allocations * @len: size of the allocation * @align: required alignment of the allocation * @flags: flags passed to heap * @handle: pointer that will be populated with a cookie to use to refer * to this allocation * * Provided by userspace as an argument to the ioctl */ struct ion_allocation_data { size_t len; size_t align; unsigned int flags; struct ion_handle *handle; };
分配好了buffer之后,如果用户空间想使用buffer,先需要mmap. ION是通过先调用IOCTL中的ION_IOC_SHARE/ION_IOC_MAP来得到可以mmap的fd,然后再执行mmap得到bufferaddress.
然后,你也可以将此fd传给另一个进程,如通过binder传递。在另一个进程中通过ION_IOC_IMPORT这个IOCTL来得到这块共享buffer了。
来看一个例子:
[html]
view plaincopyprint?
进程A:
int ionfd = open("/dev/ion", O_RDONLY | O_DSYNC);
alloc_data.len =
0x1000;
alloc_data.align = 0x1000;
alloc_data.flags =
ION_HEAP(ION_CP_MM_HEAP_ID);
rc = ioctl(ionfd,ION_IOC_ALLOC, &alloc_data);
fd_data.handle =
alloc_data.handle;
rc = ioctl(ionfd,ION_IOC_SHARE,&fd_data);
shared_fd = fd_data.fd;
进程B:
fd_data.fd = shared_fd;
rc = ioctl(ionfd,ION_IOC_IMPORT,&fd_data);
进程A: int ionfd = open("/dev/ion", O_RDONLY | O_DSYNC); alloc_data.len = 0x1000; alloc_data.align = 0x1000; alloc_data.flags = ION_HEAP(ION_CP_MM_HEAP_ID); rc = ioctl(ionfd,ION_IOC_ALLOC, &alloc_data); fd_data.handle = alloc_data.handle; rc = ioctl(ionfd,ION_IOC_SHARE,&fd_data); shared_fd = fd_data.fd; 进程B: fd_data.fd = shared_fd; rc = ioctl(ionfd,ION_IOC_IMPORT,&fd_data);
2013/02/18
相关文章推荐
- ION基本概念介绍和原理分析
- ION基本概念介绍
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- ION基本概念介绍和原理分析
- 1.ElasticSearch介绍及基本概念
- 开源ESB平台Mule 基本概念介绍