內存管理的層次
內存管理的目標
- 抽象:
- 邏輯地址空間(不考慮底層細節,只需訪問一個連續的地址空間)
- 保護:
- 獨立地址空間(不會被別的進程破壞)
- 共享
- 訪問相同內存(進程間數據傳遞)
- 虛擬化
- 更多的地址空間(把最需要的數據放入內存,暫時不需要的數據放到磁盤)
地址空間 & 地址生成
- 物理地址空間
- 邏輯地址空間
地址空間定義:
物理地址空間:主存和磁盤等硬件直接管理的地址空間
邏輯地址空間:運行的應用程序直接看到一維的線性地址空間
操作系統將邏輯地址空間映射到實際的地址空間
邏輯地址空間的生成:
c語言–編譯–>彙編語言–彙編–>機器語言(.o文件)–鏈接–>可執行文件(.exe)–載入(loader)/程序重定位–>加載到內存中去運行
c/彙編語言內的變量名和函數名實際就是地址,是名字
機器語言內已將變量符號名和函數符號名等轉化爲相應的相對連續的地址空間(邏輯地址空間),是地址的二進制
邏輯地址和物理地址的對應:
CPU的內存管理單元(MMU)中有物理地址和邏輯地址的對應關係表,當CPU要取指或數據是則根據邏輯地址查表前往對應的物理地址去取出
操作系統負責建立物理地址空間和邏輯地址空間的映射關係(建表),存在內存中,爲了加快訪問放在CPU中進行緩存。
連續內存分配:
內存碎片:
空閒內存不能被利用
- 外部碎片:在分配單元之間的未使用的內存
- 內部碎片:在分配單元內未使用的內存
分區的動態分配:
- 將應用程序加載到內存時,需要爲應用程序分配內存空間
- 應用程序在運行時,需要訪問數據,要給這些數據分配內存空間
分配策略:
- 首次適配:簡單,產生外部碎片,大的內存塊集中在內存尾部
- 最佳適配:重分配慢,和應用程序所需內存差值最小的內存塊,產生小的外部碎片,不易於後續的回收
- 最差適配:重分配慢,尋找和所需內存差值最大的內存塊,對大塊的請求造成影響
減少內存碎片的方法:
壓縮式碎片整理
交換式碎片整理(換入換出)
- 充分應用硬盤,搶佔正在等待的程序,將等待的程序載入硬盤上去,並回收他們的內存。
夥伴系統:
- 整個可分配的分區大小 2^U
- 需要的分區大小爲 2^(U-1) < s <= 2^U 時,把整個塊分配給該進程
- 如 s <= 2^(i-1) ,將大小爲 2i 的當前空閒分區劃分成兩個大小爲 2^(i-1) 的空閒分區
- 重複劃分過程,直到 2^(i-1) < s <= 2^i ,並把一個空閒分區分配給該進程
夥伴系統的實現
- 數據結構
- 空閒塊按大小和起始地址組織成二維數組
- 初始狀態:只有一個大小爲 2^U 的空閒塊
- 分配過程
- 由小到大在空閒塊數組中找最小的可用空閒塊
- 如空閒塊過大,對可用空閒塊進行二等分,知道得到合適的可用空閒塊
- 釋放過程
- 把釋放的塊放入空閒塊數組
- 合併滿足合併條件的空閒塊
- 合併條件
- 大小相同 2^i
- 地址相鄰
- 起始地址較小的塊的起始地址必須是 2^(i+1) 的倍數
非連續的內存分配:
非連續內存分配方法:
- 一個程序的物理地址空間是非連續的
- 更好的內存利用和利用,減少內碎片和外碎片
- 允許共享代碼和數據(共享庫等…)
- 支持動態加載和動態鏈接
分段
將程序的不同段分散到多個物理地址中去
-
連續的邏輯地址映射到不連續的物理地址中去
-
例如c程序中棧段,堆段,代碼段,數據段
尋址方案的實現:
段訪問機制:
- 段號
- 查詢段表查找所對應物理內存的起始地址
- 通過段表還可以查詢到段的長度限制
- 段內偏移
- 段偏移和段長度進行比較,若偏移超出段長,則該邏輯地址無效,拋出異常
PS:分段機制類似之前的動態分區,也會產生外部碎片,但是因爲程序分佈在不連續的物理地址空間,所以產生的外部碎片大大減小了。
分頁
分頁分爲頁尋址和頁幀尋址兩部分
- 頁幀(物理地址的尋址)
- 頁(邏輯地址的尋址)
分頁尋址機制:
- 頁映射到幀
- 頁是連續的虛擬內存
- 幀是非連續的物理內存
- 不是所有的頁都有對應的幀
根據邏輯地址獲取頁號p–>查詢頁表根據頁號查到幀號f—>f和邏輯地址中的偏移量o結合爲物理地址–>[2^(o的位數,例如圖中爲9)*f+o] 即爲所需要數據所在的物理地址
PS:採用分頁機制類似之前的固定分區,但分頁技術的分區相當小,一個程序可以佔據不連續的多個分區,因而大大減小了內部碎片,提高了內存利用率。
頁表
- 每個進程有一個頁表
- 頁表歲進程運行狀態的變化而動態變化
- 頁表基址寄存器存儲頁表在內存中的地址
頁存儲管理機制存在性能問題:
- 訪問一個內存單元需要訪問2次內存(訪問頁表項,訪問數據)
- 頁表可能非常大
解決方法:
- 建立快表(TLB)
- 多級頁表
- 反向頁表