- contig heap申请的是连续内存页,最大能到order 10(受限于buddy)。而system heap就只能通过order 8/4/0三种拼凑出来,凑够用户需要的内存
- contig heap没有自己的内存pool,释放时直接返还给buddy。system heap有自己的pool(分为order 8/4/0)。
//指定heap name,heap type和ops static struct ion_heap *__ion_system_contig_heap_create(void) { struct ion_heap *heap; heap = kzalloc(sizeof(*heap), GFP_KERNEL); if (!heap) return ERR_PTR(-ENOMEM); heap->ops = &kmalloc_ops; heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG; heap->name = "ion_system_contig_heap"; return heap; } static int ion_system_contig_heap_create(void) { struct ion_heap *heap; heap = __ion_system_contig_heap_create(); if (IS_ERR(heap)) return PTR_ERR(heap); //添加到ion dev,并且在/d/ion/heaps目录下创建debug节点,节点名以heap name命名:"ion_system_contig_heap" ion_device_add_heap(heap); return 0; } //开机过程中,驱动加载时创建,当然这只是参考代码,具体还要看不同平台的具体实现 device_initcall(ion_system_contig_heap_create);
static struct ion_heap_ops kmalloc_ops = { .allocate = ion_system_contig_heap_allocate, .free = ion_system_contig_heap_free, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, .map_user = ion_heap_map_user, };
直接从buddy中分配连续的内存块
static int ion_system_contig_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, unsigned long flags) { int order = get_order(len); struct page *page; struct sg_table *table; unsigned long i; int ret; //直接从buddy中分配内存页 //分配的内存页是可能比实际请求的大的,比如申请len是3个page大小,那么order就为2,实际申请了4个page page = alloc_pages(low_order_gfp_flags, order); if (!page) return -ENOMEM; //将申请到的连续内存页分割成一页页 split_page(page, order); //由于在分配时可能多分配,因此需要将多余的page释放回去。比如申请3个page,实际分配了4个 len = PAGE_ALIGN(len); for (i = len >> PAGE_SHIFT; i < (1 << order); i++) __free_page(page + i); //接着申请sg_table table = kmalloc(sizeof(*table), GFP_KERNEL); if (!table) { ret = -ENOMEM; goto free_pages; } //由于是连续的内存,因此只需要申请一个scatterlist ret = sg_alloc_table(table, 1, GFP_KERNEL); if (ret) goto free_table; //将连续内存首页地址存到sg_table中 sg_set_page(table->sgl, page, len, 0); buffer->sg_table = table; return 0; free_table: kfree(table); free_pages: for (i = 0; i < len >> PAGE_SHIFT; i++) __free_page(page + i); return ret; }
将内存全部返还给buddy
static void ion_system_contig_heap_free(struct ion_buffer *buffer) { struct sg_table *table = buffer->sg_table; struct page *page = sg_page(table->sgl); unsigned long pages = PAGE_ALIGN(buffer->size) >> PAGE_SHIFT; unsigned long i; //释放时就直接将内存页归还给buddy for (i = 0; i < pages; i++) __free_page(page + i); sg_free_table(table); kfree(table); }