system contig heap与system heap
- 从代码中我们看到system contig heap与system heap同属一个文件中,ion\_system\_heap.c
- 相同点:它们都是根据用户传递的字节len,转换成order,从buddy中申请内存页
- 不同点:
- contig heap申请的是连续内存页,最大能到order 10(受限于buddy)。而system heap就只能通过order 8/4/0三种拼凑出来,凑够用户需要的内存
- contig heap没有自己的内存pool,释放时直接返还给buddy。system heap有自己的pool(分为order 8/4/0)。
system contig heap创建
//指定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);
system contig heap内存分配
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,
};
- ion\_system\_contig\_heap\_allocate()函数分配:
直接从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;
}
system contig heap内存释放
- ion\_system\_contig\_heap\_free()函数:
将内存全部返还给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);
}