berkeley db 的記憶體管理

2022-09-09 00:03:27 字數 3633 閱讀 5549

乙個典型的 buddy system. **在env/env_alloc.c

alloc_layout: 管理整塊記憶體(即bdb的某個region)的 資料結構. 放於此記憶體 開頭位置.

sh_tailq_head(__addrq) addrq; // address queue. 按位址排序. 用於記憶體塊 的**和 合併. 所有的記憶體塊 都會放入address queue中.

#define db_size_q_count 11

sizeq_head sizeq[db_size_q_count]; // size queue. 用於快速查詢可用記憶體. 11個queue, 從1024位元組 到 1m.

// 每個queue中 的記憶體塊 按長度 從大到小 排序. size queue中放的是 當前沒有使用的記憶體.

alloc_element: 放於每乙個記憶體塊的開頭

sh_tailq_entry addrq; // 其在address queue中的entry

sh_tailq_entry sizeq; // 其在size queue中的entry

uintmax_t len; // 此記憶體塊 總的長度

uintmax_t ulen; // 使用者可用的長度

// 僅當 剩餘記憶體(空閒記憶體塊大小 - 使用者需要的大小) 大於 shalloc_fragment, 做記憶體分割

#define shalloc_fragment (sizeof(alloc_element) + 64)

// 對指定的記憶體大小len, q返回對應的 size queue. head指向當前region的 alloc_layout.

#define set_queue_for_size(head, q, i, len) do \

} while (0)

// 乙個alloc_element 占用的記憶體大小. 需做對齊

#define db_alloc_size(len) \

(size_t)db_align((len) + sizeof(alloc_element), sizeof(uintmax_t))

reginfo->head為 alloc_layout. 初始化其 address queue, size queue.

剩下的記憶體 初始化為 乙個 alloc_element, 放入address queue 和sizeq[db_size_q_count - 1]

note: 有可能 region 初始化大小 不足1m, 放入sizeq[db_size_q_count - 1]沒有關係, 第一次分配記憶體 會把其放入 合適的size queue.

基於 堆的記憶體分配(malloc), 這裡不討論.

head = infop->head;  //

此region的alloc_layout物件

total_len = db_alloc_size(len); //

需分配的記憶體大小

set_queue_for_size(head, q, i, total_len); //

找到對應的size queue

for (elp = null;; ++q)

if (elp != null || ++i >= db_size_q_count) //

在當前queue中找到; 或者查完所有size queue都未找到.

break

; }

if (elp ==null)

// 下面是已經找到合適記憶體的情況

sh_tailq_remove(q, elp, sizeq, __alloc_element);

//將其從 對應的size queue 移除.

if (elp->len - total_len > shalloc_fragment)

p = (u_int8_t *)elp + sizeof

(alloc_element);

elp->ulen = len; //

elp為返回給使用者的記憶體塊

head = infop->head; //

此region的alloc_layout物件

p =ptr;

elp = (alloc_element *)(p - sizeof(alloc_element)); //

得到需要釋放記憶體的alloc_element物件

elp->ulen = 0; //

ulen為0, 表示此記憶體不再使用

//address queue中元素按 其 位址排序.

if ((elp_tmp =sh_tailq_prev(&head->addrq, elp, addrq, __alloc_element)) != null && //

elp_tmp設為 此elp 在address queue之前的 元素

elp_tmp->ulen == 0 && //

之前的元素 未被使用

(u_int8_t *)elp_tmp + elp_tmp->len == (u_int8_t *)elp)

if ((elp_tmp = sh_tailq_next(elp, addrq, __alloc_element)) != null && //

elp_tmp設為 此elp 在adress queue之後的 元素

elp_tmp->ulen == 0 && //

之後的元素 未被使用

(u_int8_t *)elp + elp->len == (u_int8_t *)elp_tmp)

__env_size_insert(head, elp);

//合併後的 記憶體塊入 size queue

__env_size_insert(): 將某個 alloc_element 插入其對應的 size queue中.

set_queue_for_size(head, q, i, elp->len); //

找到其對應的size queue

sh_tailq_foreach(elp_tmp, q, sizeq, __alloc_element) //

遍歷此size queue

if (elp->len >= elp_tmp->len) //

size queue元素從大到小排序, elp大小位於 當前元素和前乙個元素之間(前乙個元素可能為空). 需要插入到當前elp_tmp之前

break

;

if (elp_tmp ==null)

sh_tailq_insert_tail(q, elp, sizeq);

//elp插入隊尾

else

sh_tailq_insert_before(q, elp_tmp, elp, sizeq, __alloc_element);

//elp插入到當前elp_tmp之前

: env_alloc/env_alloc_free 都未加鎖. 對其的呼叫需要 加相應region的鎖.

BerkeleyDB 的編譯和安裝

2.cd db build unix dist configure 特別注意,如果要使用其c 介面的話,請執行 dist configure enable cxx 否則不會生成libdb cxx.so.3.make 4 sudo make install 5.在你的makefile 中新增 berk...

記憶體管理 記憶體管理概述

儲存器的發展方向是高速 大容量和小體積,即儲存器嘗試更高讀寫速度,更大儲存容量,更小物理體積。在計算機中,常見的儲存器有 暫存器,快取,記憶體,硬碟,一般硬碟之類的輔助儲存器又稱外存。在平均讀寫速度上,有 暫存器 快取 記憶體 外存 在單位容量 上,有 外存 記憶體 快取 暫存器 cpu處理器只能直...

記憶體管理 記憶體的簡介

32位機器具有4g的程式記憶體,這個記憶體並不是指實際的物理記憶體,而是虛擬記憶體這個虛擬記憶體並不是實際存在的。我們知道乙個虛擬空間由一組頁對映函式將虛擬空間的各個頁對映至相應的物理空間,那麼建立乙個虛擬空間實際上並不是建立空間而是建立對映函式所需要的相應的資料結構,在i386 的linux下,建...