linux核心記憶體管理的一項重要工作就是如何在頻繁申請釋放記憶體的情況下,避免碎片的產生。linux採用夥伴系統解決外部碎片的問題,採用slab解決內部碎片的問題
buddy演算法最主要的的特點任何時候區域裡的空閒記憶體都能以2的n次方進行拆分或合併。
夥伴系統的宗旨就是用最小的記憶體塊來滿足核心的對於記憶體的請求。在最初,只有乙個塊,也就是整個記憶體,假如為1m大小,而允許的最小塊為64k,那麼當我們申請一塊200k大小的記憶體時,就要先將1m的塊**成兩等分,各為512k,這兩分之間的關係就稱為夥伴,然後再將第乙個512k的記憶體塊**成兩等分,各位256k,將第乙個256k的記憶體塊分配給記憶體,這樣就是乙個分配的過程。
演算法的核心思想:把所有的空閒頁框分組為11個塊鍊錶,每個塊鍊錶分別包含1、2、4、8、16、…、512、1024個連續頁框。
zone相關結構,參考記憶體管理(二)zone和watermark
通過pglist_data結構就可以完全的描述乙個記憶體的layout了。
start_kernel()–>paging_init()–>zone_sizes_init()–>free_area_init_nodes()–>free_area_init_node()–>free_area_init_core()–>init_currently_empty_zone()–>zone_init_free_lists()中,free_area的相關域都被初始化buddy分配器是按照頁為單位分配和釋放物理記憶體的,在zone那一節文章中freearea就是通過buddy分配器來管理的。
buddy分配器將空閒頁面按照order的大小分配掛到不同的order鍊錶中。比如order為0的鍊錶下就掛載著大小為1個page的空閒頁,order=4的鍊錶下就掛載著大小為16個page的空閒頁面。
buddy分配器的演算法是:
在真正分析分配**之前,我們需要看一下alloc_開頭的一些flag,kernel/msm-5.4/mm/internal.h
alloc_pages -> alloc_pages_node -> __alloc_pages_node -> __alloc_pages -> __alloc_pages_nodemask所有的分配頁面的函式最終都會落到__alloc_pages_nodemask這個函式上面,它是夥伴系統的入口。
* kernel/msm-
5.4/mm/page_alloc.c
struct page *
__alloc_pages_nodemask
(gfp_t gfp_mask,
unsigned
int order,
int preferred_nid,
nodemask_t *nodemask)
一般通過get_page_from_freelist分配的被稱作快速路徑,通過__alloc_pages_slowpath分配的被稱作慢速路 linux記憶體管理(五) 夥伴系統
核心中很多時候要求分配連續頁,而計算機經過長時間的執行以後,頻繁的分配和釋放記憶體,就會造成有很多記憶體雖然空閒可用,但是散布在實體地址空間的各處,這就是記憶體管理的碎片問題。為了能夠快速檢測記憶體中的連續區域,減緩碎片問題,linux核心採用了古老而歷經考驗的技術 夥伴系統。如圖所示,第一幅圖中有...
初窺記憶體管理(三)夥伴演算法
假設系統的可利用記憶體空間容量為2m個字 位址從0到2m 1 則在開始執行時,整個記憶體區是乙個大小為2m的空閒塊,在執行了一段時間之後,被分隔成若干占用塊和空閒塊。為了在分配時查詢方便起見,我們將所有大小相同的空閒塊建於一張子表中。每個子表是乙個雙重鍊錶,這樣的鍊錶可能有m 1個,將這m 1個表頭...
大神與三位小夥伴
程式設計之美資格賽2014 時間限制 2000ms 單點時限 1000ms 記憶體限制 256mb 因為方案數可能非常大,大神同學希望知道挑選紀念品的方案數模10 9 7之後的答案。第一行包括乙個數t,表示資料的組數。接下來包含t組資料,每組資料一行,包括乙個整數n。對於每組資料,輸出一行 case...