buddy演算法的優缺點:
1)儘管夥伴記憶體演算法在記憶體碎片問題上已經做的相當出色,但是該演算法中,乙個很小的塊往往會阻礙乙個大塊的合併,乙個系統中,對記憶體塊的分配,大小是隨機的,一片記憶體中僅乙個小的記憶體塊沒有釋放,旁邊兩個大的就不能合併。
2)演算法中有一定的浪費現象,夥伴演算法是按2的冪次方大小進行分配記憶體塊,當然這樣做是有原因的,即為了避免把大的記憶體塊拆的太碎,更重要的是使分配和釋放過程迅速。但是他也帶來了不利的一面,如果所需記憶體大小不是2的冪次方,就會有部分頁面浪費。有時還很嚴重。比如原來是1024個塊,申請了16個塊,再申請600個塊就申請不到了,因為已經被分割了。
3)另外拆分和合併涉及到 較多的鍊錶和位圖操作,開銷還是比較大的。
buddy(夥伴的定義):
這裡給出夥伴的概念,滿足以下三個條件的稱為夥伴:
1)兩個塊大小相同;
2)兩個塊位址連續;
3)兩個塊必須是同乙個大塊中分離出來的;
buddy演算法的分配原理:
假如系統需要4(2*2)個頁面大小的記憶體塊,該演算法就到free_area[2]中查詢,如果鍊錶中有空閒塊,就直接從中摘下並分配出去。如果沒有,演算法將順著陣列向上查詢free_area[3],如果free_area[3]中有空閒塊,則將其從鍊錶中摘下,分成等大小的兩部分,前四個頁面作為乙個塊插入free_area[2],後4個頁面分配出去,free_area[3]中也沒有,就再向上查詢,如果free_area[4]中有,就將這16(2*2*2*2)個頁面等分成兩份,前一半掛如free_area[3]的鍊錶頭部,後一半的8個頁等分成兩等分,前一半掛free_area[2]
的鍊錶中,後一半分配出去。假如free_area[4]也沒有,則重複上面的過程,知道到達free_area陣列的最後,如果還沒有則放棄分配。
buddy演算法的釋放原理:
記憶體的釋放是分配的逆過程,也可以看作是夥伴的合併過程。當釋放乙個塊時,先在其對應的鍊錶中考查是否有夥伴存在,如果沒有夥伴塊,就直接把要釋放的塊掛入煉表頭;如果有,則從鍊錶中摘下夥伴,合併成乙個大塊,然後繼續考察合併後的塊在更大一級鍊錶中是否有夥伴存在,直到不能合併或者已經合併到了最大的塊(2*2*2*2*2*2*2*2*2個頁面)。
整個過程中,位圖扮演了重要的角色,如圖2所示,點陣圖的某一位對應兩個互為夥伴的塊,為1表示其中一塊已經分配出去了,為0表示兩塊都空閒。夥伴中無論是分配還是釋放都只是相對的點陣圖進行異或操作。分配記憶體時對位圖的
是為釋放過程服務,釋放過程根據位圖判斷夥伴是否存在,如果對相應位的異或操作得1,則沒有夥伴可以合併,如果異或操作得0,就進行合併,並且繼續按這種方式合併夥伴,直到不能合併為止。
buddy記憶體管理的實現:
提到buddy 就會想起linux 下的物理記憶體的管理 ,這裡的memory pool 上實現的 buddy 系統
和linux 上按page 實現的buddy系統有所不同的是,他是按照位元組的2的n次方來做block的size
實現的機制中主要的結構如下:
整個buddy 系統的結構
:struct mem_pool_table
;這個結構是包含在free node 或alloc node 中的結構:
其中check 和 fill 都被設定為某個pattern
用來檢查該node 的合法性
#define mem_hdr_check_pattern ((uint16)0x3ca4)
#define mem_hdr_fill_pattern ((uint8)0x5c)
typedef struct tagbuddymemblockheadtype
buddy_mem_block_head_type;
這個結構就是包含node 型別結構的 free header 的結構:
typedef struct tagbuddymemheadtype
mem_free_hdr_type;
這個結構就是包含node 型別結構的 alloc header 的結構:
已分配的mem 的node 在記憶體中就是這樣表示的
typedef struct mem_alloc_hdr_type
mem_alloc_hdr_type;
其中用in_use_size 來表示如果請求分配的size 所屬的level上實際用了多少
比如申請size=2000bytes, 按size to level 應該是2048,實際in_use_size
為2000,剩下48byte 全部填充為某一數值,然後在以後free 是可以check
是否有overwite 到著48byte 中的數值,一般為了速度,只 檢查8到16byte
另外為什麼不把這剩下的48byte 放到freelist 中其他level 中呢,這個可能
因為本來buddy 系統的缺點就是容易產生碎片,這樣的話就更碎了
關於free or alloc node 的示意圖:
假設最小塊為2^4=16,著是由mem_alloc_hdr_type (12byte)決定的, 實際可分配4byte
如果假定最大max_block_size =1024,
如果pool 有mem_free_hdr_type[0]上掛了兩個1024的block node
上圖是free node, 下圖紫色為alloc node
接下來主要是buddy 系統的操作主要包括pool init , mem alloc ,mem free
pool init :
1. 將實際pool 的大小去掉mem_pool_table 結構大小後的size 放到
mem_pool_size, 並且修改實際mem_pool_ptr指向前進mem_pool_table
結構大小的位址
2. 接下來主要將mem_pool_size 大小的記憶體,按最大塊掛到free_lists 上
level 為0的list 上,然後小於該level block size 部分,繼續掛大下一
級,迴圈到全部處理完成 (感覺實際用於pool的size ,應該為減去
mem_pool_table 的大小,然後和最大塊的size 對齊,這樣比較好,
但沒有實際測試過)
mem alloc:
這部分相當簡單,先根據請求mem的size ,實際分配時需要加上mem_alloc_hdr_type
這12byte ,然後根據調整後的size,計算實際應該在那個 level上分配,如果有相應級
很簡單,直接返回,如果沒有,一級一級迴圈查詢,找到後,把省下的部分,在往下一級
一級插入到對應級的freelist 上
mem free:
其中free 的位址,減去12 就可以獲得mem_alloc_hdr_type 結構
然後確定buddy 在該被free block 前,還是後面, 然後合併buddy,
迴圈尋找上一級的buddy ,有就再合併,只到最大block size 那級
關於這個演算法,在<> vol 1,的
動態儲存分配中有描述,對於那些只有osal 的小系統,該演算法相當有用
**:
記憶體管理演算法 Buddy夥伴演算法
buddy演算法的優缺點 1 儘管夥伴記憶體演算法在記憶體碎片問題上已經做的相當出色,但是該演算法中,乙個很小的塊往往會阻礙乙個大塊的合併,乙個系統中,對記憶體塊的分配,大小是隨機的,一片記憶體中僅乙個小的記憶體塊沒有釋放,旁邊兩個大的就不能合併。2 演算法中有一定的浪費現象,夥伴演算法是按2的冪次...
記憶體管理演算法 Buddy夥伴演算法
buddy system記憶體管理,努力讓記憶體分配與相鄰記憶體合併能快速進行 對於普通演算法來講,合併記憶體相當困難 它利用的是計算機擅長處理2的冪運算。我們建立一系列空閒塊列表,每一種都是2的倍數。舉個例子,如果最小分配單元是8位元組,整個記憶體空間有1m。我們建立8位元組記憶體塊鍊錶,16位元...
夥伴演算法 Buddy
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!hi,buddy 刺蝟 關於位圖 linux核心夥伴演算法中每個order 的點陣圖都表示所有的空閒塊,比如我家的電腦記憶體256m 現在連上個qq主頁都比較卡 理論上的order為0的bitmap有256m 4k 2 塊。為什麼要除以二呢?因為 ...