計算機操作系統-內存管理

分配回收

內存中哪裏可以放?怎麼選?怎麼收回結束的進程?
傳統的存儲管理方式:

連續分配

分配區域沒有被進程使用的部分,稱內部碎片
分配區域沒有進程能使用的部分,稱外部碎片

單一連續分配
優點:沒有外部碎片,可以不用內存保護,採用覆蓋技術
缺點:(進程沒用上的)內部碎片,僅能單用戶,單任務效率很低

固定分區分配
支持多道程序
在這裏插入圖片描述
分區大小相等:死板,適用於控制多個相同對象(工廠生產)
分區大小不等:靈活,按需劃分
每個分區只裝入一道作業,使用==分區說明表(按大小排列)==記錄,進程找到第一個能滿足大小的未分配分區,記得修改分區說明表的狀態

分區號 大小(MB) 起始地址 狀態
1 y x 未分配
2 z x+y 未分配
3 n x+y+z 未分配

實現簡單,外部碎片 ×\times
進程過大時裝不下(可以使用"覆蓋" 技術搶救一下),但內部碎片\sqrt{} 效率×\times

動態分區分配
支持多道程序,又稱爲 可變分區分配 :進程裝入內存時根據進程大小動態地建立分區,分區大小和數量可變

數據結構空閒分區表     和    空閒分區鏈表

分區號 大小(MB) 起始地址 狀態
1 l s 未分配
2 m s+l+x 未分配
3 n s+l+x+m+y 未分配
大小

地址

狀態

大小

地址

狀態

大小

地址

狀態

表項的排列順序和動態分區分配算法有關,分配後記得修改相應表項狀態
回收時只要有相鄰空閒區就會合併
內部碎片×\times     外部碎片\sqrt{}
可以通過 緊湊(或拼湊,Compaction) 技術,“平移”進程塊來解決外部碎片的問題

動態分區分配算法

算法 數據結構 優點 缺點
首次適應算法(First Fit)\sqrt{} 地址排序
低到高
第一個
算法開銷小
回收不用再排序
綜合性能最佳
從頭開始–>
低地址很多外部碎片–>
查找開銷
最佳適應算法(Best Fit)×\times 空間排序
小到大
第一個
保留大分區 越來越多
外部碎片
算法開銷大
最壞適應算法(Worst Fit)×\times
(或“最大適應算法”)
空間排序
大到小
第一個
較少外部碎片 消耗大分區
大進程不友好
算法開銷大
鄰適應算法(Next Fit)×\times FF算法+循環
從上次查找結束
的位置繼續查找
小進程同BF高址留大 大進程同WF裝不下

非連續分配

支持多道程序的 固定分區分配 和 動態分區分配分別會產生內部碎片 和 外部碎片,“緊湊”算法代價很高----->內存分爲分爲多個大小相等的小分區,再按分區大小拆分進程,實現非連續內存空間存儲,分區越小內部碎片越小

基本分頁存儲管理

內存
每個分區稱爲頁框、頁幀、內存塊、物理塊(多數4KB)
每個都有號碼(頁框號、頁幀號、內存塊號、物理塊號)
進程
被分爲與頁框大小相等頁(或頁面)物理單位
對應的號碼爲頁號
訪問過程

邏輯地址

計算頁號
查詢

頁的起始地址
計算頁內偏移量
物理地址=頁起始地址+頁內偏移量

其中假設地址32bit,頁面4KB=212B,按字節尋址邏輯地址

頁號 頁內偏移量
31~12 11~0
220-1<3Byte 使用2的整數冪做頁面大小方便計算

每個進程創建一張頁表(慢表)

頁號 =頁表起始地址 + 頁號×\times 3Byte (順序存儲+表項等大=隱藏) 物理塊號(頁框號)

表項按頁號順序存儲,每頁可存4KB=1365×3B+1B4KB= 1365\times3B+1B
但爲了方便查表,常使用4B存儲一個表項(沒有內部碎片1B)

兩級頁表
一個進程最大220個頁面,頁表大小 = 222B = 210×\times 4KB,需要1024個連續的頁框才能存下
局部性原理:一段時間內集中訪問若干頁面–>其他頁面不用常駐內存
再分組:爲離散分配的頁表再建 “頁目錄表” (or 外層頁表 or 頂層頁表)

一級頁號 二級頁號 頁內偏移量
31~22 (210) 21~12 (210) 11~0 (212)

基本地址變換機構
邏輯地址 轉換 物理地址 的一組硬件機構
在這裏插入圖片描述
快表
時間局部性:被執行的指令很可能再次被執行,被訪問數據很可能再次被訪問(循環指令)
空間局部性:被訪問存儲單元附近的單元很可能近期被訪問(數組)
局部性原理 導致多次重複查詢同一頁號 + 高速緩衝寄存器(cache) = 快表 (TLB,Translation Lookaside Buffer)
在這裏插入圖片描述
命中則只需要“取數據”僅次內存訪問,未命中則需要"慢表查詢”+“數據訪問"次內存訪問
“快表”溢出需要用算法找出可以替換的頁表項

基本分段存儲管理

邏輯單位 進程地址劃分爲若干段(編譯器:段名–> 基址),每段佔用一個連續空間,邏輯地址:

段號 段內地址

段表

段號(順序存儲+表項等大=隱藏) 段長 基址
2段號位 2段內地址位 內存地址空間4GB=232B

同樣可以使用"快表"
在這裏插入圖片描述

基本段頁式存儲管理

基本分頁存儲 基本分段存儲管理
一個邏輯地址=一個物理地址(一維) 段名+段長(二維)
物理單位,系統行爲 邏輯單位,用戶行爲
大小固定=無外部碎片 容易實現信息的共享保護
信號量機制 等“可重入”/“純” 代碼
保護部分和共享部分在頁內分不開 大小可變=長段沒”坑“,有外部碎片

段頁式管理 = 邏輯分段+每段分頁 ,從而同時獲取兩種管理方式的優點

用戶指定

段號 段內地址

系統根據段內地址分配 頁號 與 頁內地址 得到邏輯地址

段號 頁號 頁內偏移量

段表

段號(順序存儲+表項等大=隱藏) 頁表長度 物理塊號(頁框號)

頁表

頁號(順序存儲+表項等大=隱藏) 物理塊號(頁框號)

在這裏插入圖片描述
三次內存訪問,引入快表{段號;頁號;物理地址}可以減少至一次

空間擴充

覆蓋與交換

覆蓋: (同一個進程中)程序按功能分段(模塊)
用戶必須指明覆蓋的結構,增加用戶負擔
在這裏插入圖片描述
交換: (不同進程間)就是中級調度,換出空間需求大的進程,換入需求小的進程
由就緒態 轉換爲 就緒掛起時,PCB還是常駐內存中
內存喫緊時,降低系統負荷,反映在缺頁率在這裏插入圖片描述

虛擬內存

局部性原理 + 高速緩衝技術

傳統的存儲管理機制 虛擬內存技術
作業一次性裝入內存
大程序無力,併發度下降
多次性
訪問的局部性
駐留性 --> 浪費資源
對換性

實際容量=min(內存+外存,最大容量=2CPU尋址位數)
操作系統提供 請求調頁/請求調段+頁面置換/段置換 功能

請求分頁存儲管理

頁表增加了頁面狀態的描述字段

頁號(順序存儲+表項等大=隱藏) 物理塊號(頁框號) 狀態位 訪問字段 修改位 外存地址
始址+頁號×\times表項大小 物理地址 內存中? 訪問次數
訪問時間
被寫? 文件結構

在這裏插入圖片描述
表中有省略
被“擠出快表”(從快表中刪除)的表項要在慢表中修改相應的表項
被”寫“過的表項“修改位”變化,沒被寫過的表項“置換”時可以不用拷貝回外存
I/O操作慢,頻繁置換開銷很大
在這裏插入圖片描述

頁面置換算法

挑選 “內存中暫時用不到的塊” 換出到外存,好的算法缺頁率低,磁盤I/O少
缺頁率=\frac{缺頁次數}{總訪問次數}

最佳置換算法(Opt,Optimal)
淘汰最長時間內不會再使用的頁面

訪問順序 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
內存塊0 7 7 7 2 - 2 - 2 - - 2 - - 2 - - - 7 - -
內存塊1 - 0 0 0 - 0 - 4 - - 0 - - 0 - - - 0 - -
內存塊2 - - 1 1 - 3 - 3 - - 3 - - 1 - - - 1 - -
缺頁統計 - - - - - - - - - - -

7號頁面之後出現時間最晚,被換出,其他類推
缺頁率=920\frac{9}{20}=45%
無法預知頁面訪問順序無法實現,作爲比較基準

先進先出置換算法(FIFO)
淘汰最早進入的頁面

訪問順序 3 2 1 0 3 2 4 3 2 1 0 4
內存塊0 3 3 3 0 0 0 4 - - 4 4 -
內存塊1 - 2 2 2 3 3 3 - - 1 1 -
內存塊2 - - 1 1 1 2 2 - - 2 0 -
缺頁統計 - - -

3號頁面最早出現,被換出,其他類推
缺頁率=912\frac{9}{12}=75%
增加內存塊數可能導致某些訪問順序( 如上 )會出現Belady異常(缺頁率反而變大)
最先進入的通常爲常駐塊( 如main函數等 )
性能最差

最近最久未使用置換算法(LRU,least recently used)
淘汰最早開始沒有被使用的已駐頁面

頁號(順序存儲+表項等大=隱藏) 物理塊號(頁框號) 狀態位 訪問後計時 修改位 外存地址
訪問順序 1 8 1 7 8 2 7 2 1 8 3 8 2 1 3 1 7 1 3 7
內存塊0 1 1 - 1 - 1 - - - - 1 - - - - - 1 - - -
內存塊1 - 8 - 8 - 8 - - - - 8 - - - - - 7 - - -
內存塊2 - - - 7 - 7 - - - - 3 - - - - - 3 - - -
內存塊2 - - - - - 2 - - - - 2 - - - - - 2 - - -
缺頁統計 - - - - - - - - - - - - - -

7號頁面最早開始沒有被使用,被置換
缺頁率=620\frac{6}{20}=30%
性能最好,但開銷大,需要硬件支持

時鐘置換算法(CLOCK)
又稱“最近未使用算法(NRU,Not Recently Used)”
被訪問置1,需要置換時,(最多2圈)循環檢查並置零訪問位,淘汰訪問位0的頁面

頁號(順序存儲+表項等大=隱藏) 物理塊號(頁框號) 狀態位 訪問位 修改位 外存地址

在這裏插入圖片描述

改進型時鐘置換算法
在時鐘置換算法基礎上,不改變修改位狀態,訪問位相同時優先淘汰沒有被修改過的頁面
未修改 = 不用回寫磁盤 = 節省時間

頁號(順序存儲+表項等大=隱藏) 物理塊號(頁框號) 狀態位 訪問位 修改位 外存地址
- - - (0 0) -

第一輪:找(0,0) = {沒訪問,沒修改}
第二輪:沒找到(0,0)就找(0,1) = {沒訪問,有修改},置0訪問位
第三輪:沒找到(0,1)就找(0,0) = {有訪問,沒修改}
第四輪:沒找到(0,0)就第一個(0,1) = {有訪問,有修改}
替換以上步驟找到的頁面
在這裏插入圖片描述
性能最均衡

頁面分配策略

駐留集:系統分配給進程的物理塊集合(採用虛擬存儲技術的系統 駐留集 < 進程大小)

. 局部置換(自身物理塊) 全局置換(空閒 或 其他進程非核心物理塊)
駐留集大小不變 = 固定分配 固定分配局部置換
駐留集大小可變 = 可變分配 可變分配局部置換 可變分配全局置換

固定分配局部置換:根據進程大小、優先級等參數確定駐留集
可變分配局部置換:根據缺頁率動態調整駐留集大小,只能置換自己的頁
可變分配全局置換:只要缺頁一定得到新的物理塊,先找空閒塊,再找其他進程非核心(未鎖)塊

調入時機
1.預調頁:= 空間局部性預測,或用戶指定,主要用於首次調入(運行前調入)
2.請求調頁 = 缺頁 才 調頁,磁盤IO開銷大

調入源頭
在這裏插入圖片描述
抖動(顛簸):同一個頁面頻繁的換入換出內存
原因可能是駐留集不夠,導致頻繁訪問的頁面放不下,催生出了 = = 》
(Denning)工作集某段時間內(窗口尺寸) 進程實際訪問的頁面集合
根據工作及調整駐留集大小(駐留集<工作集 便會抖動),或置換駐留集中的非工作集頁面

請求分段存儲管理

請求段頁式存儲管理

地址轉換

編譯
鏈接
編譯
鏈接
裝入程序
鏈接
source.cpp
目標模塊.obj

地址 0-49
裝入模塊.exe

完整邏輯地址 0-99
source.cpp
目標模塊.obj

地址 0-49
內存

起始地址+邏輯地址
庫文件.lib

相對地址=邏輯地址
絕對地址=物理地址

尋址空間 = 2地址總線位
尋址範圍 = 0x00 ~ \frac{\tiny 內存大小 }{\tiny 字大小}
按字節尋址
存儲單元 = 1Byte = 8 bit =最小的編址
按字尋址
存儲單元 = 1 Word = (16/32/64)8\frac{(16 / 32 / 64)} { 8 } Byte

鏈接方式

得到完整的邏輯地址
靜態鏈接
鏈接—>(.exe)—>裝入—>內存
裝入動態鏈接
(.obj)—>裝入+鏈接–>內存
運行動態鏈接
運行時—>需要(.obj) or (.lib) —>鏈接—>內存
可以共享模塊,易於修改

裝入方式

地址的轉換:邏輯地址—>物理地址
絕對裝入
(.cpp){邏輯地址} —> 編譯 —> (.obj){物理地址}
單道程序環境
靜態重定位
又稱 可重定位裝入
(.cpp){邏輯地址} —> 編譯 —> (.obj){邏輯地址} —> 裝入 —> 內存{物理地址}
要求連續全部內存空間,運行期間更不可移動!
多道批處理系統
動態重定位
又稱 動態運行時裝入
(.cpp){邏輯地址} —> 編譯 —> (.obj){邏輯地址} —> 裝入 —> 內存{邏輯地址} —> 執行時

起始地址
重定位寄存器

邏輯地址
+
物理地址

允許進程移動,分配不連續存儲區,可以共享程序段!!
現代操作系統

存儲保護

保證進程互不干擾
方法一:cpu{上下限寄存器}
方法二:

邏輯地址
最大邏輯地址
起始物理地址
CPU
越界?
界地址寄存器

限長寄存器
越界異常
+
重定位寄存器

基址寄存器
實際物理地址
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章