內存管理的目標:
-
實現內存的分配和回收
-
合理的分配內存空間,提高內存利用率,提高內存訪問速度
存儲器的層次結構
速度由快到慢,容量由小到大,價格由高到低
寄存器->L1高速緩存 -> L2高速緩存 -> 主存儲器 -> 本地二級存儲 -> 遠程二級存儲(web/ftp)
特點:每個層級的存儲器都保存來自下一級存儲器的信息
分類:
-
其中位於CPU內部的是:寄存器->L1高速緩存 -> L2高速緩存
-
其中統稱為內存的是:寄存器->L1高速緩存 -> L2高速緩存 -> 主存儲器
-
其中統稱為外存/輔助存儲的是:本地二級存儲 -> 遠程二級存儲(web/ftp)
局部性原理
定義:在一段時間內,程序的執行僅限於某個部分,相應的,它所訪問的存儲空間也局限於某個區域
分類
-
時間局部性
- 程序的執行僅限於某個部分(某幾條指令)
- 某指令一旦被執行,不久之后該指令將再次被執行
-
空間局部性
- 程序所訪問的內存僅限於某個部分,
- 若某個單元的內存被訪問,則附近的單元將很快被訪問
程序的鏈接
靜態鏈接
含義: 程序被編譯后會變成一個一個的獨立模塊(比如用到的各種庫),在運行前,需要使用鏈接程序將目標模塊鏈接成一個完整的裝入模塊
特點:運行速度相對快,但占用內存更多
鏈接程序的具體任務
- 鏈接程序的任務
- 對邏輯地址進行修改
- 鏈接程序的任務2
- 變換外部調用符號
- 外部認為程序依然是整體的,所以使用的是Call,但是現在程序被分成不同模塊,所以鏈接程序需要將外部的call變換為JSR(跳轉至子程序)
動態鏈接
含義:可將目標模塊的鏈接推遲到這這寫模塊中的函數被調用時才進行;
特點:運行速度相對慢,但是可以節省內存
程序的裝入
連接程序完成連接后得到一個裝入模塊,裝入程序負責將這個裝入模塊裝入到內存中
絕對裝入方式
編譯時產生物理地址的目標代碼
重定位裝入方式
- 可重定位裝入方式(靜態重定位) ,編譯時地址是邏輯地址, 裝入時通過重定位轉換為物理地址
- 動態運行時裝入(動態重定位),程序執行時通過重定位轉為物理地址
實際地址 = 邏輯地址 + 物理其實地址
連續分配存儲管理方式
單一連續分配
任何時刻主存儲器最多只有一個作業
固定分區分配
- 將內存分為固定大小的若干個分區,每個分區可以且僅可以裝入一個作業
- 根據系統不同,分區大小可以是相等也可以是相等的
- 每個分區有上限寄存器和下限寄存器,統稱為界限寄存器,用於保護內存
- 維護一個
固定分區說明表
用於記錄分區的使用情況
動態分區分配
- 分區大小不是預先固定的,而是按照作業的實際需求來划分的
- 分區的個數也不是預先固定的,而是由能裝入的作業數決定的
- 維護一個
空閑分區表
,用於記錄當前可用的分區信息
-
與空閑分區表功能相同的還有另一種叫做
空閑分區鏈
-
本質是一個雙向鏈表,每個節點包含一個指向前一個和一個指向后一個分區的指針,以及一個保存可用分區起始地址和長度的數據域;
-
動態分區分配算法
首次適應算法
- 空閑分區鏈以地址遞增的順序鏈接,從鏈首開始查找直至找到第一個滿足條件的分區
- 從該分區中划出一塊內存給進程,剩下的分區信息仍然留在空閑鏈中
- 該方式的不足
- 外部碎片,分配后剩下的一點點留在分區鏈中,由於空間較小,無法被有效利用
- 內部碎片已經分配個某個進程的空間,但進程不需要那么多,空閑了一部分
循環首次適應算法
- 唯一與首次適應算法不同的就是,維護了一個分區指針,每次分配完成,該指針往后移動一個位置;
- 該方式可使得空閑區分布較均勻,但是依然會產生碎片
最佳適應發
- 每次分配前需將分區鏈節點按照空閑空間大小從小到大排序
- 遍歷分區鏈,查找第一個滿足條件的分區分配給進程,
- 該方式可使得每次分配都能盡可能找到與進程需求最接近的分區,減少碎片產生,提高利用率
動態分區分配流程
設使用最佳適應算法,流程已經介紹不在啰嗦
- 對分區鏈按照大小升序排序
- 遍歷分區鏈在找到可用分區后,從分區中划出區域給進程
- 更新分區鏈信息
例:設找到的分區起始位置為S,長度為L, 進程需要的大小為N
-
分配完成后,新的起始位置為:S + N, 長度為L - N
-
重新對分區鏈按空間大小升序排序
動態分區回收流程
- 釋放一塊連續的內存區域
- 如果被釋放的區域與其他空閑區域前后相鄰則將前后相鄰的分區合並,無論在前在后
- 如果沒有相鄰的,則創建新節點存儲分區信息
- 修改分區鏈信息
例:
-
設釋放的區域起始地址為A,長度為L
-
判斷否相鄰:設已有空閑分區起始位置為X,長度為Y
- 若 X+Y == A ,則表示前面有相鄰, 則合並后空閑分區起始地址為X,長度為Y + L
- 若 A+L == X,則表示后面有相鄰,則合並后空閑分區起始地址為A,長度為L + Y