android6.0已經把binder_buffer有關的操作和binder.c分開了,實現在binder_alloc.c檔案裡面
一、binder_alloc_mmap_handler函式進行map,先看這個結構體:
struct binder_alloc ;
引數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) else
if (size > buffer_size)
n = n->rb_right;
else
}if (n == null)
在free_buffers查詢適當的記憶體,看一下
static size_t binder_alloc_buffer_size(struct binder_alloc *alloc,
struct binder_buffer *buffer)
如果只有乙個成員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))
}if (alloc->buffers.next !=
&buffer->entry)
}binder_insert_free_buffer(alloc, buffer);
這部分先看看能不能和相鄰的free_buffer裡的binder_buffer合併,能合併則合併,然後把最終的binder_buffer插入進free_buffer裡面。
總結:兩個紅黑樹儲存已分配和未分配的buffer,臨近的free_buffer會被合併,free_buffer紅黑樹
便於查詢大小合適的塊進行分配,allocated_buffer儲存位址便於查詢和釋放,其它的先不分析。
水平有限,如有錯誤,敬請指正。
記憶體分配 Go記憶體管理 記憶體分配一
go作為乙個比較新晚 新 的語言,自然借鑑前輩們的優點,比如說語言本身負責記憶體管理 對協程和高併發的高優支援 簡單高效的語法等。本篇及後續的幾篇要講的就是還沒提到的比較複雜的記憶體管理。學習記憶體管理 分配 前,如果有jvm的記憶體管理的基礎,會變得非常簡單,如果是第一次接觸記憶體管理,在看完go...
記憶體分配 定長記憶體分配器
在各種記憶體分配演算法中,有一種很實用,實現起來也簡單 定長的記憶體分配器。即每次分配的記憶體大小是固定的。大概邏輯是 在一些區域性的單執行緒邏輯中,可以有效提高效率。很短,很容易看懂 fallocator.h pragma once 固定長度的記憶體分配器 include include incl...
靜態記憶體分配和 動態記憶體分配
1 靜態記憶體分配是在編譯時完成的,不需要占用cpu資源 動態分配記憶體是在執行時完成的,動態記憶體的分配與釋放需要占用cpu資源 2 靜態記憶體分配是在棧上分配的,動態記憶體是堆上分配的 3 動態記憶體分配需要指標或引用資料型別的支援,而靜態記憶體分配不需要 4 靜態分配記憶體需要在編譯前確定記憶...