Upload
carson-ramirez
View
41
Download
2
Embed Size (px)
DESCRIPTION
使用 C/C++ 語言. 楊正宏 編著 全華科技圖書股份有限公司 印行. 第十一章 動態記憶體管理 (1/2). 11-1 前言 11-2 記憶體分配方法 11-3 邊界標識法 (Boundary Tag Method) 11-3-1 可利用空間串列的結構 11-3-2 分配演算法 11-3-3 回收演算法 11-4 夥伴系統 (Buddy System) 11-4-1 可利用空間串列的結構 11-4-2 分配演算法 11-4-3 回收演算法. 第十一章 動態記憶體管理 (2/2). - PowerPoint PPT Presentation
Citation preview
1
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
楊正宏 編著全華科技圖書股份有限公司 印行
使用 C/C++ 語言
2
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
第十一章 動態記憶體管理 (1/2)
• 11-1 前言• 11-2 記憶體分配方法• 11-3 邊界標識法 (Boundary Tag Method)
– 11-3-1 可利用空間串列的結構– 11-3-2 分配演算法– 11-3-3 回收演算法
• 11-4 夥伴系統 (Buddy System) – 11-4-1 可利用空間串列的結構– 11-4-2 分配演算法– 11-4-3 回收演算法
3
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
第十一章 動態記憶體管理 (2/2)
• 11-5 費氏夥伴系統 (Fibonacci Buddy System)• 11-6 廢置單元收集• 11-7 廢置單元收集的改良• 11-8 記憶體壓縮
4
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
前言 (1/2)
• 透過作業系統取得所需記憶體 (memory) ,並在執行完成後將所佔記憶體歸還作業系統,此項管理工作便稱為「動態記憶體管理」。
• 動態記憶體管理的基本工作是系統如何因應使用者提出的 "記憶體分配需求 ",以及如何 "回收 (釋放 )" 記憶體,以便當新的 "請求 "產生時,重新進行分配。
5
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
前言 (2/2)
• 系統執行初期
• 系統執行若干時間之後
U1 U2 U3 U4 U5 U6
位址低 位址高
U1 U3 U4 U6
位址低 位址高
6
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
記憶體分配方法 (1/2)
• 常用的三種方法包括:– 最先合適法 (First-Fit)
– 最佳合適法 (Best-Fit)
– 最差合適法 (Worst-Fit)
• 根據可利用閒置串列的多寡可分:– 單一區段– 多區段
7
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
記憶體分配方法 (2/2)
• 最先合適法 (First-Fit) :– 自可供利用空間區段中,找到第一塊大於 n 的閒置區段,將其中
一部份分配給使用者;回收時,只要將釋放的閒置區段插入在鏈結串列的開頭即可。
• 最佳合適法 (Best-Fit) :– 自可供利用空間區段中,找出一塊大小最接近 n 的閒置區段分配
給使用者。為避免搜尋浪費的時間,先將區段自小到大排序。分配時,只需找到第一個大於 n 的閒置區段即可分配;回收時,必須將釋放的閒置區段插入到合適的位置上去。
• 最差合適法 (Worst-Fit) :– 自可供利用閒置區段中,找出最大的閒置區段分配給使用者。將
閒置區段由大到小排序。每次分配時,只需將第一個區段的其中一部份分配給使用者即可;回收時,亦需將釋放的閒置區段插入到適當位置上去。
8
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
三種分配方法的比較圖 分配法
項目
最先合適法 最佳合適法 最差合適法
適用時機系統事先不掌握執行期間分配和回收的訊息情況。
適用於分配記憶體範圍較廣的系統。
適用在分配記憶體範圍較窄的系統。
分配方法
分配隨機,介於最佳與最差兩者之間,需查詢可利用空間區段。
進行分配時,找最接近請求的閒置區段,需搜尋鏈結串列,最費時間。
必須從記憶體最大的節點中進行分配,使得鏈結串列中節點大小趨於平衡,無需查詢鏈結串列。
回收方法僅需插入串列開頭即可。
需先進行搜尋,將新的“閒置區段”插入鏈結串列中適當的位置。
需先進行搜尋,將新的“閒置區段“插入鏈結串列中適當的位置。
優 點配置速度快。 配置後,殘餘之空
間為最小,但無法供其他作業使用。
配置後,殘餘之空間為最大,尚可供其他使用者使用。
9
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
邊界標識法 (Boundary Tag Method) (1/8)
• 是一種作業系統中用以進行動態分區分配的記憶體管理方法
• 配合最先合適法來管理記憶體,可減少搜尋時間。 • 特點:
– 在於每個記憶體區段的開頭部份和尾部兩個邊界上分別設有標籤,以標識該區域為占用區段或閒置區段,使得在回收使用者釋放的閒置區段時,易於判別物理位置上與其相鄰的記憶體區域是否為閒置區段,以便將所有位址中連續的閒置記憶體區組合成一個大的閒置區段。
10
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
邊界標識法 (2/8)
• 起始狀態
• 執行若干時間後
• 進行再分配後的狀態
0 100K
0
pav
590031001000
0 1500
0
pav
0 0800
0
0 4100
pav
5900310010000 1500
0
0 0800
0
0 4100
0
可利用空間串列的結構
11
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
邊界標識法 (3/8)
• 分配演算法規定: – 假設所找到的閒置區段的容量為 m個字組 (包括頭部和底部 ),而每次分配只是從中分配 n個字組給使用者,剩餘 m-n 個字組大小的節點仍留在鏈結串列中,則在若干次分配之後,鏈給串列中會出現一些容量極小而分配不出去的閒置區段,這就大大減慢了分配 (搜尋 )的速度。
– 彌補的辦法是:選定一個適當的常量 e,當 m-n≦e時,將容量為 m的閒置區段整塊分配給使用者;反之,只分配其中 n個字的記憶體。同時,為了避免修改指標,約定將該節點中位址較大部份分配給使用者。
12
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
邊界標識法 (4/8)
• 分配演算法規定:– 如果每次分配都從同一個節點開始搜尋的話,勢必造成記憶體小的節點集中在開頭指標 pav 所指節點附近,反而增加查詢較大閒置區段的時間。反之,如果每次分配從不同的節點開始進行搜尋,使分配後剩餘的小區段均勻地分布在鏈結串列中,則可避免上述弊病。
– 可行的方法是每次分配之後,令指標 pav指向剛進行過分配的節點的後繼節點。
13
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
邊界標識法 (5/8)
• 回收演算法– 釋放區段的左、右鄰區均為佔用區段的情況
•只要作簡單插入即可。由於在按最先合適法進行分配時邊界標識法對可利用空間串列的結構並沒有任何要求,則新的閒置區段插入在串列中任何位置均可。
•簡單的做法就是插入在 pav指標所指節點之前( 或之後 ) 。
14
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
邊界標識法 (6/8)
• 回收演算法– 釋放區段約左鄰區為閒置區段,而右鄰區為佔用區段的情況•由於釋放區段的開頭部份和左鄰閒置區段的尾部毗鄰,因此只要改變左鄰閒置區段的節點,增加節點 size欄的值,且更新設置節點的尾部即可。
20,000
0 30,000
左鄰區釋放區段
0
15
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
邊界標識法 (7/8)
• 回收演算法– 釋放區段的右鄰區為閒置區段,左鄰區為佔用區段
•由於釋放區段的尾部和右鄰閒置區段的開頭部份毗鄰,當串列中節點由原來右約有鄰閒置區段變成合併後的大閒置區段時,區段的尾部指標位置不變,但開頭的指標位置要移動,因此,鏈結串列中的指標也必須要移動。
0 35,000
釋放區段右鄰區
0
0 15,000
右鄰區
16
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
邊界標識法 (8/8)
• 回收演算法– 釋放區段的左、右鄰區均為閒置區段
•為使三個閒置區段連接在一起成為一個大閒置區段留在可利用空間串列中,只要增加左鄰閒置區段的 space 容量,同時在鏈結串列中刪去右鄰閒置區段節點即可。
0 45,000
左鄰區
右鄰區0
0 15,000
右鄰區 釋放區段
17
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
夥伴系統 (Buddy System) (1/7)
• 一種動態記憶體之管理方法。和邊界標識法類似 • 使用者提出申請時,分配一塊大小“適當”的記憶體
給使用者;反之,在使用者釋放記憶體時即回收。 • 無論是佔用區段或閒置區段,其大小均為 2 的次方值。
• 當使用者申請 n 大小的記憶體時,就分配區段大小為 2
k個字組 (byte) 給它,其中 2k-1 n 2≦ ≦ k。 • 在可利用空間串列中的閒置區段大小只能是 2 的次方值。若可利用記憶體容量為 2m,則閒置區段的大小只可能為 20, 21,‥, 2m。
18
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
夥伴系統 (2/7)
• 可利用空間串列的結構
串列的初始狀態
headerllink rlinkkvaltag=0
space
空間區段的節點結構
20
21
2k
2m
^
^
^
Nodesize first
0 m
19
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
夥伴系統 (3/7)
• 分配演算法
20
2k-1
2k
2m
^
^
^
0 k 0 k 0 k
分配前的串列
節點 3 節點 2 節點 1
20
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
夥伴系統 (4/7)
• 分配演算法
0 k-120
2k-1
2k
2m
^
^
0 k 0 k
用剩餘的另一半節點
節點 2 節點 3
21
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
夥伴系統 (5/7)
• 假設從 2k子串列中刪除的節點的起始位址為 p ,且假設分配給使用者的佔用區段的初始位址也為 p ,則插入上述子串列的新節點的起始位址分別為 p+2k-i, p+2k-i+1,…, p+2k-1 如圖所示
2k
(低位址區) P 使用P+2k-3
未使用P+2k-2
未使用(高位址區)
P+2k-1 未使用
22
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
夥伴系統 (6/7)
• 回收演算法 – 在使用者釋放佔用區段時,系統需將此閒置區段插入到可利用閒置區段中去。
– 在夥伴系統中同樣也有一個位址相鄰的閒置區段合併成大區段的問題,但是在夥伴系統中僅考慮 "互為夥伴 " 的合併。
空閒區段 A 空閒區段 B 0
A1 A2 A3
23
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
夥伴系統 (7/7)
• 優點:– 演算法較簡單、速度快。
• 缺點:– 由於只合併伙伴,容易產生碎片。
24
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
費氏夥伴系統 (Fibonacci Buddy System) (1/3)
• 費氏的分配系統
21
8
5
2
13
5 8
3
3
25
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
費氏夥伴系統 (2/3)
• 重點不在分配記憶體的區塊,而是兩個具有共同父節的相鄰區塊,如何合併成較大的區塊。
• 為了記憶體釋回工作操作順利,設定 counter變數,以記錄區塊的分裂關係,步驟:– 使用區塊中最大者,即節點 counter = 0
– 當區塊分裂為二時,以遞迴方式定義 counter 的值: 左區塊的 counter = counter+1 。 右區塊的 counter = 0 ( 歸零 ) 。
26
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
費氏夥伴系統 (3/3)
• 每個區塊填上 counter數字
1 0
21
8
5
2
13
5 8
3
3
1
2
0
counter = 0
010
27
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
廢置單元收集 (1/5)
• 是使用者不再使用而沒有回收的記憶體區段。 • 特點在於使用者請求記憶體時進行分配,在使用者釋放記憶體時進行回收 。
P2
P1
1
1
1
P3
28
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
廢置單元收集 (2/5)
• 參考計數法 (Reference Count Method):在所有子串列或一般化串列上增加一個串列開頭節點,並設立一個“計數器”,每當有一指標指向此節點則計數器加 1直到計數器為 0時,節點才被釋放。
• 收集廢置單元 (Garbage Collection):在程式執行的過程中,對所有的鏈結串列節點,不管它是否還有用,都不回收,直到整個記憶體用完。當記憶體用完時,才暫時中斷執行程式,將之前釋放的記憶體空間回收當作使用者使用的空間,當記憶體用完時,再度執行此動作。
29
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
廢置單元收集 (3/5)
• 收集廢置單元的方式分兩階段進行:– 標示階段 (marking phase): 對所有佔用節點加上標示,可在每個節點上再加設一個標示 (mark) ,以區別是否為正在作用中的區段。
– 搜集階段 (collection phase): 當記憶體不夠時收集標示為非在作用區段的記憶體。
30
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
廢置單元收集 (4/5)
• 遞迴的演算法:– 若串列為空,則不走訪;若有資料,則作標示。– 在允許使用遞迴的高階語言中非常容易撰寫。– 需要使用堆疊,由於串列的層次無法估計,使得堆疊的容量不易確定,除非是在記憶體中宣告一個相當大的堆疊空間,否則標示時,可能因為超過堆疊空間而使系統癱瘓。
31
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
廢置單元收集 (5/5)
• 非遞迴的演算法:– 類似圖形的兩種優先搜尋 (DFS和 BFS) ,可分為縱向或橫向。
– 當串列非空時,使用橫 (縱 )向優先搜尋走訪時,在對串列節點加標示後,先順串列開頭指標逐層向下對串列開頭加標示,同時將同 (下 )層非空且未加標示的串列尾端指標依次推入堆疊,直到串列開頭為空串列或為元素節點時停止,然後退出堆疊取出上一層的串列尾端指標。
– 反覆上述程序,直到堆疊空為止。
32
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
記憶體壓縮 (1/4)
• 做法: – 當有使用者釋放記憶體即進行回收壓縮。– 在程式執行過程中不回收使用者隨時釋放的記憶體,直到可利用空間不夠分配或區塊指標指向最高位址時才進行記憶體壓縮。此時壓縮的目的是將區塊中所有的閒置區段連成一片,即將所有的佔用區段都集中到可利用空問的低位址區,而剩餘的高位址區成為一整個位址連續的閒置區段。
33
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
記憶體壓縮 (2/4)
• 壓縮後前記憶體
0 1 2 3 4 5 6 78162432
A1 0 5A2 5 6A3 11 3A4 14 5
起始
位址 長度
34
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
記憶體壓縮 (3/4)
• 壓縮後的記憶體
0 1 2 3 4 5 6 78
162432
A1 0 5A2A3 5 3A4 8 5
起始
位址 長度
35
第十一章 動態記憶體管理
資料結構使用 C/C++ 語言
記憶體壓縮 (4/4)
• 記憶體壓縮前 記憶體壓縮後
pointer pointer
壓縮