Linux核心筆記 記憶體管理之塊記憶體分配

2022-05-04 04:12:09 字數 2532 閱讀 9183

核心版本:linux-2.6.11

夥伴系統是linux用於滿足對不同大小塊物理記憶體分配和釋放請求的解決方案。

linux將物理記憶體分成三個記憶體管理區,分別為zone_dmazone_normalzone_highmem,並使用三個管理區描述符管理這三個zone。

管理區描述符裡,有乙個元素數為11的free_area陣列,分別對應1、2、4、8、16.....不同塊的大小,其中的每個元素的型別都是乙個名為free_area的結構體,**位置mm/mmzone.h

struct free_area ;
例如,該陣列第三個元素的free_list儲存了2的4次方即16個頁框大小的空閒塊鍊錶,nr_free儲存了空閒塊的數量。

**位置mm/page_alloc.c

__rmqueue,傳入引數為order和管理區zone的描述符指標。

static struct page *__rmqueue(struct zone *zone, usigned int order);
該函式會遍歷2的order次方個頁框大小的塊空閒鍊錶,若該鍊錶空,則將order+1繼續遍歷,找到非空的空閒塊鍊錶後,取得它的第乙個頁框描述符。

page = list_entry(area->free_list.next, struct page, lru);
list_entry是乙個巨集,功能是取得乙個成員變數的父結構體的指標,這裡的意思是獲得第乙個引數area->free_list.next所在的page結構體的指標。

接著從鍊錶中刪除它的這乙個頁框描述符,並減少管理區描述符中的free_pages的值。

從上述過程可以知道,在獲取order對應大小的空閒塊時,如果沒有正好大小的空閒塊,那麼將會從更大的空閒塊中分離出order對應大小的空閒塊,分離後剩下的部分要按照夥伴系統的規則正確的記錄到管理區描述符的free_area陣列中,expand函式在做這件事的同時,將我們需要的空閒塊的第乙個頁框描述符的private欄位設定成order(因為這個private仍然是空閒塊未分割時的order值)。

return expand(zone, page, order, current_order, area);
至此,已經找到了需要的空閒塊,返回其中的第乙個頁框描述符指標。

**位置mm/page_alloc.c

__free_pages_bulk,傳入引數依次為要釋放塊的第乙個頁框描述符的指標,管理區的zone_mem_map字段(即管理區中的第乙個頁框描述符指標),管理區描述符,釋放塊的order值

static inline void __free_pages_bulk (struct page *page, struct page *base,

struct zone *zone, unsigned int order)

除去一些報錯的**後,主要過程就是尋找這個釋放塊的夥伴,並將二者合併。

函式實現部分,尋找夥伴這部分的**理解起來比較晦澀,但十分聰明

buddy_idx = (page_idx ^ (1 << order));

buddy = base + buddy_idx;

page_idx是釋放塊在zone_mem_map中的下標,為了尋找它的夥伴塊在zone_mem_map中的下標,將page_idx與塊大小進行異或操作,該步驟可以將page_idx的第order位取反,即可以得到比page_idx高乙個塊大小的下標或者比page_idx低乙個塊大小的下標,這個下標值就是釋放塊的夥伴塊在zone_mem_map中的下標。接著呼叫函式page_is_buddy來檢查該夥伴塊是否可以合併,若不行,退出迴圈,若行,將order+1並繼續迴圈尋找是否有更大的夥伴塊可以合併。

coalesced = base + page_idx;

set_page_order(coalesced, order);

list_add(&coalesced->lru, &zone->free_area[order].free_list);

zone->free_area[order].nr_free++;

迴圈結束後,page_idx記錄了合併塊的第乙個頁框描述符在zone_mem_map中的下標,加上base即zone_mem_map本身的位址後,得到合併塊的第乙個頁框描述符的指標coalesced(這單詞也夠隱晦),該合併塊成為最終的釋放塊,更新第乙個頁框描述符的private欄位,並將其插入到適當鍊錶,最後再增加該鍊錶空閒塊數量。

至此,塊記憶體釋放結束。

Linux 2 6核心筆記 記憶體管理

4月14日 很多硬體的功能,物盡其用卻未必好過軟實現,linux出於可移植性及其它原因,常常選擇不去過分使用硬體特性。比如 linux只使用四個segment,分別是 user cs user ds kernel cs kernel ds,因為paging可以完成segmentation的工作,而且...

Linux 記憶體管理之核心態剖析

記憶體管理不僅是 linux 系統中比較難理解的模組,更是網上資料講解混亂的模組。本場 chat 旨在讓讀者了解記憶體分配的來龍去脈,從硬體原理和核心角度出發,分析如下內容 cpu 通過 mmu 訪問實體地址的原理 記憶體的 zone 劃分 dma normal 和 highmem 記憶體的 pag...

linux核心學習筆記之記憶體管理

linux核心把物理頁作為記憶體管理的基本單位。每一頁的大小根據系統架構不同有所區別,32位系統下為4kb,64位系統下為8kb。記憶體管理單元 mmu 以頁為單位來管理系統中的頁表,負責虛擬位址到實體地址的轉換,使用者所使用的記憶體位址一般都是虛擬位址。核心中頁的結構體中比較重要的成員為 stru...