Binder 記憶體分配

2021-08-09 03:51:33 字數 3400 閱讀 9546

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 靜態分配記憶體需要在編譯前確定記憶...