Binder 内存分配
来源:互联网 发布:sql中别名 编辑:程序博客网 时间:2024/06/10 02:21
android6.0已经把binder_buffer有关的操作和binder.c分开了,实现在binder_alloc.c文件里面
一、binder_alloc_mmap_handler函数进行map,先看这个结构体:
struct binder_alloc { struct mutex mutex; struct vm_area_struct *vma; struct mm_struct *vma_vm_mm; void *buffer; // map 的地址就是这里了 ptrdiff_t user_buffer_offset; //内核空间和用户空间的差 struct list_head buffers; //所有的buffers列表 struct rb_root free_buffers; //只进行了预定,没有分配,按大小排序 struct rb_root allocated_buffers; //已经分配了,按地址排序 size_t free_async_space; //用于异步请求的空间 struct binder_lru_page *pages;//所有的pages size_t buffer_size; //总共的大小 uint32_t buffer_free; int pid;};
参数alloc和proc相关,也就是每个进程一个,vma用户调用传入参数
int binder_alloc_mmap_handler(struct binder_alloc *alloc,
struct vm_area_struct *vma);
这个函数流程比较简单,关键流程如下:
1、
area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP); alloc->buffer = area->addr; alloc->user_buffer_offset =vma->vm_start - (uintptr_t)alloc->buffer;
预定空间,初始化alloc的buffer和user_buffer_offset变量.
2、
alloc->pages = kzalloc(sizeof(alloc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);
分配pages的空间
3、
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); buffer->data = alloc->buffer; list_add(&buffer->entry, &alloc->buffers); buffer->free = 1; binder_insert_free_buffer(alloc, buffer); alloc->free_async_space = alloc->buffer_size / 2;
往free_buffer里放置一个buffer,设置free_async_space为总空间的一半
二、binder_alloc_new_buf 分配一个binder_buffer,调用了binder_alloc_new_buf_locked
关键流程如下:
1、计算需要分配的空间大小
2、
struct rb_node *n = alloc->free_buffers.rb_node; while (n) { buffer = rb_entry(n, struct binder_buffer, rb_node); BUG_ON(!buffer->free); buffer_size = binder_alloc_buffer_size(alloc, buffer); if (size < buffer_size) { best_fit = n; n = n->rb_left; } else if (size > buffer_size) n = n->rb_right; else { best_fit = n; break; } } if (n == NULL) { buffer = rb_entry(best_fit, struct binder_buffer, rb_node); buffer_size = binder_alloc_buffer_size(alloc, buffer); }
在free_buffers查找适当的内存,看一下
static size_t binder_alloc_buffer_size(struct binder_alloc *alloc, struct binder_buffer *buffer){ if (list_is_last(&buffer->entry, &alloc->buffers)) return (u8 *)alloc->buffer + alloc->buffer_size - (u8 *)buffer->data; return (u8 *)binder_buffer_next(buffer)->data - (u8 *)buffer->data;}
如果只有一个成员alloc的结束地址减去buffer的开始地址,比如binder_alloc_mmap_handler调用后
此时buffer只有一个成员buffer->data和alloc->buffer相同,返回总的大小。
否则free_buffer的下一个开始减去自己的开始,从这里看,binder_buffer的数据应该是连续的分配
在alloc申请的空间buffer里的。
2、
ret = binder_update_page_range(alloc, 1, (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr);
前面是对齐等操作,然后binder_update_page_range分配页面了。
3、
rb_erase(best_fit, &alloc->free_buffers); buffer->free = 0; buffer->free_in_progress = 0; binder_insert_allocated_buffer_locked(alloc, buffer); binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd got %pK\n", alloc->pid, size, buffer); buffer->data_size = data_size; buffer->offsets_size = offsets_size; buffer->async_transaction = is_async; buffer->extra_buffers_size = extra_buffers_size;
从free_buffers中移除,添加到allocated_buffer,内存分配完成。
三、释放
binder_buffer void binder_alloc_free_buf(struct binder_alloc *alloc, struct binder_buffer *buffer)
1、
ret = binder_update_page_range(alloc, 1, (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr);
释放页面
2、
rb_erase(&buffer->rb_node, &alloc->allocated_buffers); buffer->free = 1;
从已分配红黑树中移除
3、
if (!list_is_last(&buffer->entry, &alloc->buffers)) { struct binder_buffer *next = binder_buffer_next(buffer); if (next->free) { rb_erase(&next->rb_node, &alloc->free_buffers); binder_delete_free_buffer(alloc, next); } } if (alloc->buffers.next != &buffer->entry) { struct binder_buffer *prev = binder_buffer_prev(buffer); if (prev->free) { binder_delete_free_buffer(alloc, buffer); rb_erase(&prev->rb_node, &alloc->free_buffers); buffer = prev; } } binder_insert_free_buffer(alloc, buffer);
这部分先看看能不能和相邻的free_buffer里的binder_buffer合并,能合并则合并,然后把最终的binder_buffer插入进free_buffer里面。
总结:两个红黑树存储已分配和未分配的buffer,临近的free_buffer会被合并,free_buffer红黑树
便于查找大小合适的块进行分配,allocated_buffer存储地址便于查找和释放,其它的先不分析。
水平有限,如有错误,敬请指正。
- Binder 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- 内存分配
- spring 下载地址
- 转载海子的《浅谈Java中的对象和引用》,对于岗入门的java菜鸟,收益匪浅呀
- Intellij IDEA中使用MyBatis-generator 自动生成MyBatis代码
- SQOOP部署及简单使用
- NGUI DrawCall
- Binder 内存分配
- python打不开数据集(有歧义的文件名)
- Android之camera架构---open之指定ID
- 以例子给出CRF的理解
- Windows 10系统MarkdownPad2 预览失败
- 【重磅】MDA以24亿美元终将DigitalGlobe收入囊中
- SolrDocument与实体类转换
- 欢迎使用CSDN-markdown编辑器
- Linux下的lds链接脚本简介(一)