Android ION内存管理

ION是Android引入的一种避免内存碎片化的内存管理方式,用于分配连续或不连续内存。为了满足各种场景下的内存分配要求,ION引入了内存heap的概念.一个内存heap定义和实现了内存分配的方式或者用途.

 

1.内存heap

1.1 heap类型

enum ion_heap_type {
    ION_HEAP_TYPE_SYSTEM,//分配的物理页面不保证是连续的.类似于vmalloc的实现
    ION_HEAP_TYPE_SYSTEM_CONTIG,//分配连续的物理页面,类似与kmalloc的实现
    ION_HEAP_TYPE_CARVEOUT,//从保留内存分配连续物理页面,且把内存添加到memory pool管理
    ION_HEAP_TYPE_CHUNK,//从保留内存分配chunk size个不连续的内存,且把内存添加到memory pool管理
    ION_HEAP_TYPE_DMA,//从伙伴系统分配连续物理内存,一般通过CMA内存来实现
    ION_HEAP_TYPE_CUSTOM, /* //平台商自定义heap类型,可以自定义内存分配方式.
                   * must be last so device specific heaps always
                   * are at the end of this enum
                   */
    ION_NUM_HEAPS = 16,
};

1.2 heap结构体和实现函数

struct ion_heap {/*只保留重要变量 */
    struct plist_node node;//系统所有的heap都要链接到ion_device
    struct ion_device *dev;//目前系统有且仅有一个ion_device
    enum ion_heap_type type;//heap 类型
    struct ion_heap_ops *ops;//heap需要实现的内存操作函数集,如果alloc/free/map_user/map_kernel等等
    struct shrinker shrinker;//注册到内存回收的回调函数,因为heap一般会有memory pool.
};

比如系统heap的内存操作集函数

static struct ion_heap_ops system_heap_ops = {
    .allocate = ion_system_heap_allocate,//负责分配内存,通过alloc_pages实现
    .free = ion_system_heap_free,//释放内存,会做memory pool缓存
    .map_dma = ion_system_heap_map_dma,//DMA操作,一般范围SG地址
    .unmap_dma = ion_system_heap_unmap_dma,//umap
    .map_kernel = ion_heap_map_kernel,//把物理内存映射到内核,通过vmap实现(dma heap除外)
    .unmap_kernel = ion_heap_unmap_kernel,
    .map_user = ion_heap_map_user,//把物理内存映射到用户空间,通过remap_pfn_range函数实现(dma heap除外)
    .shrink = ion_system_heap_shrink,
};

1.3 注册heap到ion core

ion系统,可以分为两个层次,ion core和ion heap

ion core负责实现通用API接口,而ion heap负责各种heap内存分配.

创建ion device : ion_device_create

 创建heap         : ion_heap_create

 添加heap到ion : ion_device_add_heap

 

2. ion常用API和数据结构

驱动会注册misc   /dev/ion导出给用户空间使用. 以ioctl command来交互

定义了6种 ioctl 接口,可以与用户应用程序交互。
    ION_IOC_ALLOC: 分配内存ion_alloc,最终会调用具体heap的alloc函数
    ION_IOC_FREE:ion_free 释放内存
    ION_IOC_MAP/ION_IOC_SHARE: ion_share_dma_buf_fd创建文件描述符来实现mmap和共享内存
    ION_IOC_IMPORT: ion_import_dma_buf通过fd来获取对应的buffer
    ION_IOC_CUSTOM: 调用用户自定义的ioctl

这里需要关注ION_IOC_MAP/ION_IOC_SHARE,会创建虚拟的file结点,设置dma的mmap操作集,把ion与文件系统关联起来,.这样用户才能对内存进行mmap操作

2.1 常用数据结构

  ion_device,系统有且只有一个,通过ion_device_create创建

struct ion_device {
    struct miscdevice dev;// misc device 结构体/dev/ion
    struct rb_root buffers;//系统所有ion_buffer红黑树
    struct plist_head heaps;//系统所有heap的优先级链表
    struct rb_root clients;//系统所有client的红黑树链表
    /*在/sys/kernel/debug/ion目录生成调试接口 */

    struct dentry *debug_root;
    struct dentry *heaps_debug_root;
    struct dentry *clients_debug_root;
};

ion_client表示一个客户端,也就是内存的申请者,通过ion_client_create创建

struct ion_client {
    struct rb_node node;//链接到ion_device红黑树
    struct ion_device *dev;//ion_device
    struct rb_root handles;// client分配的内存红黑树,一个handles表示一个内存引用.
    struct task_struct *task;//分配进程
    struct dentry *debug_root;//调试接口
};

ion_buffer表示一次内存分配,在ion_alloc中分配.

struct ion_buffer {
    struct kref ref;//ion_buffer本身引用
    struct rb_node node;//链接到ion_client
    struct ion_device *dev;//ion deivice
    struct ion_heap *heap;// 指向分配的heap
    void *vaddr;//内核虚拟地址
    struct sg_table *sg_table;//sg散列表,
    struct page **pages;//具体的page
    /* used to track orphaned buffers */
    int handle_count;//buffer应用计数
    char task_comm[TASK_COMM_LEN];//进程名
};

ion_handle可以理解为ion_buffer的一个引用

struct ion_handle {
    struct kref ref;//ion handle计数
    struct ion_client *client;//指向分配者
    struct ion_buffer *buffer;//ion buffer
    struct rb_node node;//链接到ion_client红黑树
};

3. 使用案例

3.1用户空间

void main()
{
    int *p;
    struct ion_fd_data fd_data;
    struct ion_allocation_data ionAllocData;
    ionAllocData.len=0x1000;
    ionAllocData.align = 0;
    ionAllocData.flags = ION_HEAP_TYPE_SYSTEM;
    int fd=open("/dev/ion",O_RDWR);
    ioctl(fd,ION_IOC_ALLOC, &ionAllocData);
    fd_data.handle = ionAllocData.handle;
    ioctl(fd,ION_IOC_SHARE,&fd_data);
        p=mmap(0,0x1000,PROT_READ|PROT_WRITE,MAP_SHARED,fd_data.fd,0);
    p[0]=99;
    perror("test");
    printf("hello all %d\n",p[0]);
}

3.2内核空间

extern struct ion_device *g_idev;

void allocfromion()
{
    int *buf;
    struct ion_handle *data;

    client = ion_client_create(g_idev, -1, "kernel");
    data = ion_alloc(client,0x1000,0,ION_HEAP_SYSTEM_MASK);
    
    buf = ion_map_kernel(client,data);
}

4. 调试接口

/sys/kernel/debug/ion/buffer//系统所有buffer

/sys/kernel/debug/ion/client//打印client使用内存情况

/sys/kernel/debug/ion/event//alloc/free/mmap等事件

/sys/kernel/debug/ion/heap//各种堆的使用情况

 

 

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值