ION框架学习(一)
来源:互联网 发布:mac怎么关闭软件 编辑:程序博客网 时间:2024/06/05 14:08
第一章介绍:ION的框架和buffer的分配;
第二章介绍:如何使用ION buffer;
ION是google在Android4.0 为了解决内存碎片管理而引入的通用内存管理器,用来支持不同的内存分配机制,如CARVOUT(PMEM),物理连续内存(kmalloc), 虚拟地址连续但物理不连续内存(vmalloc), IOMMU等
(一)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表示。
下面是整个框架的类图:
说明如下:
在driver初始化过程中会创建ion_device,并提供给用户层ioctrl接口;不同平台根据定义好的platform data heap类型创建heap,同时指定这写heap操作使用的方法接口;不同类型的heap连接成链表,保存在通过plist_head heap;
需要使用heap,先注册client,不同的heap有多个client来使用,连接成链表保存在rb_root client;不同的client跟不同的进程pid绑定;
ion_handle管理实际ion_buffer, 成员id:唯一表示ion_buffer的整型变量,通过内核的idr机制加上这个id就可以在其它进程中访问到这块buffer。而且上层在传下来的struct ion_allocation_data结构体中也只是保存了这个id。
用户空间和内核空间都可以成为client,不过创建的方法稍稍有点区别;
内核空间:先创建client,有了client之后就可以分配内存,有了handle也就是buffer之后就准备使用了,不过还是物理地址,需要map:
用户空间:用户空间如果想使用ION,也必须先要创建client,不过它是打开/dev/ion,实际上它最终也会调用ion_client_create。不过和内核空间创建client的一点区别是,用户空间不能选择heap type(使用预订的heap id隐含heap type),但是内核空间却可以。另外,用户空间是通过IOCTL来分配内存的,cmd为ION_IOC_ALLOC.
ion_fd = open("/dev/ion", O_ RDONLY | O_SYNC); ioctl(ion_fd, ION_IOC_ALLOC, alloc);
分配好了buffer之后,如果用户空间想使用buffer,先需要mmap. ION是通过先调用IOCTL中的ION_IOC_SHARE/ION_IOC_MAP来得到可以mmap的fd,然后再执行mmap得到buffer address.然后你也可以将此fd传给另一个进程,如通过binder传递。在另一个进程中通过ION_IOC_IMPORT这个IOCTL来得到这块共享buffer了。
(二)ION Device和Heap创建
通过ION device和driver匹配之后走入ion_drv_probe()函数:
kernel-4.4/drivers/staging/android/ion/mtk/ion_drv.c686 static int ion_drv_probe(struct platform_device *pdev) //创建ion device,name为ion,并提供应用层操作接口ion_fops;创建调试节点:/sys/kernel/debug/ion693 g_ion_device = ion_device_create(ion_custom_ioctl); //ion_custom_ioctl soc自定义的ioctl操作;698 699 /* create the heaps as specified in the board file */700 for (i = 0; i < num_heaps; i++) {701 struct ion_platform_heap *heap_data = &pdata->heaps[i];702 struct ion_heap *heap;703 704 if (heap_data->type == ION_HEAP_TYPE_CARVEOUT && heap_data->base == 0) {705 /* reserve for carveout heap failed */706 heap_data->size = 0;707 continue;708 }709 710 heap = ion_mtk_heap_create(heap_data);714 715 ion_device_add_heap(g_ion_device, heap);716 }
这个函数首先创建一个设备ion_device,通过ion_device_create()来创建,传入一个给到用户层面用的ioctl函数:
539 static long _ion_ioctl(struct ion_client *client, unsigned int cmd,540 unsigned long arg, int from_kernel) {541 long ret = 0;542 543 ION_FUNC_ENTER;544 switch (cmd) {545 case ION_CMD_SYSTEM:546 ret = ion_sys_ioctl(client, cmd, arg, from_kernel);547 break;548 case ION_CMD_MULTIMEDIA:549 ret = ion_mm_ioctl(client, cmd, arg, from_kernel);550 break;551 } 552 ION_FUNC_LEAVE;553 return ret;554 }
处理的ioctrl命令有:
30 enum ION_MM_CMDS { 31 ION_MM_CONFIG_BUFFER, 32 ION_MM_SET_DEBUG_INFO, 33 ION_MM_GET_DEBUG_INFO, 34 ION_MM_SET_SF_BUF_INFO, 35 ION_MM_GET_SF_BUF_INFO, 36 ION_MM_CONFIG_BUFFER_EXT 37 }; 38 39 enum ION_SYS_CMDS { 40 ION_SYS_CACHE_SYNC, 41 ION_SYS_GET_PHYS, 42 ION_SYS_GET_CLIENT, 43 ION_SYS_SET_HANDLE_BACKTRACE, 44 ION_SYS_SET_CLIENT_NAME, 45 ION_SYS_DMA_OP, 46 };
不同的平台实现这些方式不一样,然后根据ion_platform_data表示平台定义的各种类型的heap数据类型来分配heap,以高通平台是定义在dts里面,mtk平台定义在驱动当中,举例如下:
742 static struct ion_platform_heap ion_drv_platform_heaps[] = {743 {744 .type = ION_HEAP_TYPE_SYSTEM_CONTIG,745 .id = ION_HEAP_TYPE_SYSTEM_CONTIG,746 .name = "ion_system_contig_heap",747 .base = 0,748 .size = 0,749 .align = 0,750 .priv = NULL,751 },752 {753 .type = ION_HEAP_TYPE_MULTIMEDIA,754 .id = ION_HEAP_TYPE_MULTIMEDIA,755 .name = "ion_mm_heap",756 .base = 0,757 .size = 0,758 .align = 0,759 .priv = NULL,760 },761 {762 .type = ION_HEAP_TYPE_MULTIMEDIA,763 .id = ION_HEAP_TYPE_MULTIMEDIA_FOR_CAMERA,764 .name = "ion_mm_heap_for_camera",765 .base = 0,766 .size = 0,767 .align = 0,768 .priv = NULL,769 },
根据ion_platform_data定义的heap类型然后接下来分配ion heap结构,不同的heap类型代表不同的分配方式:
37 enum ion_heap_type { 38 ION_HEAP_TYPE_SYSTEM, //通过vmalloc分配内存; 39 ION_HEAP_TYPE_SYSTEM_CONTIG, //通过kmalloc分配内存; 40 ION_HEAP_TYPE_CARVEOUT, //在保留内存块中(reserve memory)分配内存; 41 ION_HEAP_TYPE_CHUNK, //模块; 42 ION_HEAP_TYPE_DMA, 43 ION_HEAP_TYPE_CUSTOM, //由客户自己定义 47 ION_NUM_HEAPS = 16, 48 };
mtk平台又根据heap data存储的数据对象分为:
19 enum mtk_ion_heap_type { 20 ION_HEAP_TYPE_MULTIMEDIA = 10, 21 ION_HEAP_TYPE_FB = 11, 22 ION_HEAP_TYPE_MULTIMEDIA_FOR_CAMERA = 12, 23 ION_HEAP_TYPE_MULTIMEDIA_SEC = 13, 24 ION_HEAP_TYPE_MULTIMEDIA_MAP_MVA = 14, 25 ION_HEAP_TYPE_MULTIMEDIA_PA2MVA = 15, 27 };
以ION_HEAP_TYPE_MULTIMEDIA数据类型为例,heap的创建最后通过ion_mm_heap_create()实现:
//不同type的heap需要不同的method去分配,不过都是用struct ion_heap_ops来表示; 537 static struct ion_heap_ops system_heap_ops = { 538 .allocate = ion_mm_heap_allocate, 539 .free = ion_mm_heap_free, 540 .map_dma = ion_mm_heap_map_dma,//map the memory for dma to a scatterlist; 541 .unmap_dma = ion_mm_heap_unmap_dma, 542 .map_kernel = ion_heap_map_kernel,//map memory to the kernel; 543 .unmap_kernel = ion_heap_unmap_kernel, 544 .map_user = ion_heap_map_user, 545 .phys = ion_mm_heap_phys,//get physical address of a buffer; 546 .shrink = ion_mm_heap_shrink, 547 .page_pool_total = ion_mm_heap_pool_total, 548 }; static const unsigned int orders[] = { 1, 0 }; //两个内存池,为别为2^1k和2^0k; 799 struct ion_heap *ion_mm_heap_create(struct ion_platform_heap *unused) 800 { 801 struct ion_system_heap *heap; 802 int i; 803 804 heap = kzalloc(sizeof(*heap), GFP_KERNEL); 805 if (!heap) { 806 IONMSG("%s kzalloc failed heap is null.\n", __func__); 807 return ERR_PTR(-ENOMEM); 808 } 809 heap->heap.ops = &system_heap_ops; 810 heap->heap.type = ION_HEAP_TYPE_MULTIMEDIA; 811 heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; 812 heap->pools = kcalloc(num_orders, sizeof(struct ion_page_pool *), GFP_KERNEL); 813 if (!heap->pools) 814 goto err_alloc_pools; 815 heap->cached_pools = kcalloc(num_orders, sizeof(struct ion_page_pool *), GFP_KERNEL); 816 if (!heap->cached_pools) { 817 kfree(heap->pools); 818 goto err_alloc_pools; 819 } 820 //创建两种大小类型的pool,后面的alloc就会根据order在这里面分配; 821 for (i = 0; i < num_orders; i++) { 822 struct ion_page_pool *pool; 823 gfp_t gfp_flags = low_order_gfp_flags; 824 825 if (orders[i] > 0) 826 gfp_flags = high_order_gfp_flags; 827 828 if (unused->id == ION_HEAP_TYPE_MULTIMEDIA_FOR_CAMERA) 829 gfp_flags |= __GFP_HIGHMEM | __GFP_MOVABLE; 831 pool = ion_page_pool_create(gfp_flags, orders[i]);//主要初始化这个pool; 832 if (!pool) 833 goto err_create_pool; 834 heap->pools[i] = pool; 835 836 pool = ion_page_pool_create(gfp_flags, orders[i]); 837 if (!pool) 838 goto err_create_pool; 839 heap->cached_pools[i] = pool; 840 } 860 }169 struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order)170 { 171 struct ion_page_pool *pool = kmalloc(sizeof(struct ion_page_pool),172 GFP_KERNEL); 173 if (!pool) {174 IONMSG("%s kmalloc failed pool is null.\n", __func__);175 return NULL;176 }177 pool->high_count = 0;178 pool->low_count = 0; 179 INIT_LIST_HEAD(&pool->low_items); //每一个pool都包含了高地址和低地址的双向链表;180 INIT_LIST_HEAD(&pool->high_items);181 pool->gfp_mask = gfp_mask | __GFP_COMP;182 pool->order = order;183 mutex_init(&pool->mutex);184 plist_node_init(&pool->list, order);185 186 return pool;187 }
(三)添加ION client
内核和用户空间都会可以创建ion client,用户空间open ion设备来创建client,MTK封装了一层mt_ion_open(),最终调用ion_client_create()来创建;区别在与用户层创建的name是根据pid:
5693 pIon_client = ion_client_create(g_ion_device, "camera_isp");
kernel-4.4/drivers/staging/android/ion/ion.c:826 struct ion_client *ion_client_create(struct ion_device *dev, 827 const char *name) 828 { 829 struct ion_client *client; 830 struct task_struct *task; 831 struct rb_node **p; 832 struct rb_node *parent = NULL; 833 struct ion_client *entry; 834 pid_t pid; 835 841 get_task_struct(current->group_leader); 842 task_lock(current->group_leader); 843 pid = task_pid_nr(current->group_leader); 848 if (current->group_leader->flags & PF_KTHREAD) { 849 put_task_struct(current->group_leader); 850 task = NULL; 851 } else { 852 task = current->group_leader; 853 } 854 task_unlock(current->group_leader); 855 856 client = kzalloc(sizeof(struct ion_client), GFP_KERNEL); 857 if (!client)858 goto err_put_task_struct; 859 860 client->dev = dev; 861 client->handles = RB_ROOT; 862 idr_init(&client->idr); 863 mutex_init(&client->lock); 864 client->task = task; 865 client->pid = pid; 866 client->name = kstrdup(name, GFP_KERNEL); 867 if (!client->name) 868 goto err_free_client; 869 870 down_write(&dev->lock); 871 client->display_serial = ion_get_client_serial(&dev->clients, name); 872 client->display_name = kasprintf( 873 GFP_KERNEL, "%s-%d", name, client->display_serial); 874 if (!client->display_name) { 875 up_write(&dev->lock); 876 goto err_free_client_name; 877 } //把该clinet放到ion device的红黑树列表里面; 878 p = &dev->clients.rb_node; 879 while (*p) { 880 parent = *p; 881 entry = rb_entry(parent, struct ion_client, node); 882 883 if (client < entry) 884 p = &(*p)->rb_left; 885 else if (client > entry) 886 p = &(*p)->rb_right; 887 } 888 rb_link_node(&client->node, parent, p); 889 rb_insert_color(&client->node, &dev->clients); 890 891 client->debug_root = debugfs_create_file(client->display_name, 0664, 892 dev->clients_debug_root, 893 client, &debug_client_fops); 894 if (!client->debug_root) { 895 char buf[256], *path; 896 897 path = dentry_path(dev->clients_debug_root, buf, 256); 898 pr_err("Failed to create client debugfs at %s/%s\n", 899 path, client->display_name); 900 } 901 902 up_write(&dev->lock); 903 904 return client; 905 914 }
- ION框架学习(一)
- ION框架学习(二)
- Android的ion相关学习(一)
- ion学习
- ION-DTN网络设计思想(一)
- Android的ion相关学习(二)
- Android联网框架Ion
- JavaScript框架学习(一)
- yii框架学习(一)
- 次世代框架学习(一)
- spring框架学习(一)
- Netty框架学习(一)
- MINA框架学习 (一)
- Spring框架学习(一)
- Spring框架学习(一)
- spring框架学习(一)
- spring框架学习(一)
- iOS框架学习(一)
- matlab2c使用c++实现matlab函数系列教程-geomean函数
- Java学习路线图
- codeforces 850B Arpa and a list of numbers
- mysql学习----索引
- jquery $.ajax status为200 却调用了error方法
- ION框架学习(一)
- 使用AIDL,客户端调用和Service回调,以及一些需要注意的细节
- Java获取代理地址和端口
- 利用生产者消费者模式实现HTTP接口的异步调用
- 使用openlayers 3 在线加载天地图及GeoServer发布的地图
- linux下mysql开启远程访问权限及防火墙开放3306端口
- Jenkins+git+webhook自动触发部署和测试任务
- matlab2c使用c++实现matlab函数系列教程-harmmean函数
- Android studio 错误: 程序包 不存在