問題思考
- 為什么進行內存管理
- 頁式管理中每個頁表項大小的下限如何決定
- 多級頁面解決了什么問題,帶來了什么問題
內存管理的基本原理和要求
- 英文:(Memory Management), 計算機硬件盡管很大,但依然不能一次將所有用戶的進程和系統所需要的程序全部裝入主存(通常稱 16G,8G內存指的就是這個主存,他比硬盤速度快,便於程序的的調度),因此操作系統必須對內存空間進行合理的划分和有效的動態分配,這就是操作系統的概念
- 有效的內存管理在多道程序設計上非常重要,他不僅可以方便用戶使用存儲器,提高內存利用率,還可以通過虛擬技術來擴充存儲器
內存管理的主要功能有
- 內存空間的分配與回收: 由操作系統完成主存儲器空間的分配和管理,使程序員擺脫存儲分配的麻煩,提高編程效率
- 地址轉換: 在多道程序環境下,程序中的邏輯地址與內存中的物理地址不可能一致,因此存儲地址必須提供地址變換功能,把相應的邏輯地址變換為物理地址
- 內存空間的擴充: 利用虛擬存儲技術或自動覆蓋技術,從邏輯上擴充內存
- 存儲保護: 保證各道作業在各自的存儲空間內運行,互不干擾
程序的裝入和接入
- 編譯: 由編譯程序將用戶的源代碼編譯稱若干目標模塊
- 鏈接: 由鏈接程序將編譯后形成的一組目標模塊及其所需的庫函數鏈接在一起,形成一個完整的裝入模塊
- 裝入: 由裝入程序將裝入模塊裝入內存運行
可以類比做菜的過程
將菜炒熟(編譯)-> 將多道加工熟的食材組合道一起(鏈接) -> 盛出裝入道碗中(裝入)
程序的鏈接方式
- 靜態鏈接: 在程序運行之前,先將各模塊和目標以及它們所需要的庫函數鏈接成一個完成的可以執行程序(如系統內置的一些硬件程序,為了提高讀寫效率,裝入到內存提高讀寫效率)
- 裝入時動態鏈接: 將用戶源程序編譯后所得到的一組目標模塊,在裝入內存時,采用邊裝入邊鏈接的方式(如啟動時加載的動態庫)
- 運行時動態鏈接: 在程序執行中需要改模塊時菜進行的,比如 framework的懶加載過程,適合調試用,減少調用時間(代碼實現流程復雜,庫依賴關系不好把控,類比iOS 動態庫懶加載)
程序裝入內存的實現方式
- 絕對裝入: 在編譯時就已經知道程序將駐留在內存的某個位置,如早起的單道處理系統,編譯時產生程序絕對地址目標代碼,通常情況下采用的是符號地址,編譯或者匯編時候再轉化為絕對地址 (事先知道地址)
- 可重定位裝入: 在多道程序環境下,多個模塊的起始地址通常都是從0開始,根據裝入內存的開始地址加上程序地址的偏移量,將程序裝入內存. 地址的變換通常是一次裝入完成的,也稱作為靜態重定位
(考點: 一次裝入,靜態,裝入后不可改變,根據當前內存情況,裝入適當的位置) - 動態運行時裝入: 也成為動態重定位, 程序在內存中若發生移動,則需要采用動態裝入的方式,裝入程序把裝入模塊裝入內存后,並不立即把裝入模塊的相對地址轉換為絕對地址,而是把這種地址推遲到程序真正要執行的時候菜進行 (不是地址轉換為絕對地址,需要重定位寄存器)
邏輯地址空間與物理地址空間
- 編譯后每個目標模塊都是從0號單元開始編址, 成為該目標模塊的邏輯地址或相對地址
- 當鏈接程序將各個模塊鏈接成一個完成可執行的目標程序時,鏈接程序依次按各個模塊的相對地址構成同意的從0號單元開始變址的邏輯地址空間
- 用戶和程序猿只需要知道邏輯地址,不同的進程可以有相同的邏輯地址,這些相同的邏輯地址可以映射到主存的不同位置
- 物理地址空間: 內存中物理單元的集合,它是地址轉換的最終地址。進程在運行執行指令和訪問數據,最后都要通過物理內存從主存中存取。當裝入程序將可執行代碼裝入內存時,必須通過地址轉換將邏輯地址轉換為物理地址,這個過程稱為地址重定位。
內存保護
- 內存分配前,需要保護操作系統不受用戶進程影響,同時保護用戶進程不受其他用戶進程的影響,內存保護可采取兩種方法
- 在CPU中設置一對
上
,下
限寄存器,存放用戶作業在主存中的下限和上限地址,每當CPU要訪問一個地址時,分別和兩個寄存器的值進行相比,判斷是否有越界 - 采用重定位寄存器(或基地址寄存器)和界地址寄存器(又稱限長寄存器), 重定位寄存器含有最好的物理地址, 界地址寄存器含有邏輯地址最大值, 通過他們的之間的關系就能清除的知道是否越界
- 在CPU中設置一對
- 內存分配前,需要保護操作系統不受用戶進程影響,同時保護用戶進程不受其他用戶進程的影響,內存保護可采取兩種方法
內存的覆蓋與交換技術
- 覆蓋:
- 特點: 打破了必須將進程的信息全部裝入內存菜能執行的限制
- 實現: 將用戶空間分為若干固定區和覆蓋區,活躍部分放在固定區,其余部分按照調用關系分段, 首相將需要訪問的段放入覆蓋區域,其他段放在外存中,在需要調用前,系統將其調入覆蓋區,替換覆蓋區中原有的段
交換:
- 把處於等待狀態的(或者CPU調度原則下被剝奪運行權利)的程序從內存移動到輔存,把內存空間騰出來,這一過程叫做換出; 把准備好競爭CPU運行的程序從輔存轉移到內存中,換入.
交換需要注意的問題:
- 需要備份存儲,通常是快速磁盤,必須足夠大,提供對這些內存映像的直接訪問
- 為了有效使用CPU,需要保證進程執行時間比交換時間長,不然就頻繁交換,得不到提升,影響交換時間主要是轉移時間,它們是正比關系
- 喚出進程時需要保證該進程處於完全空閑狀態
- 交換空間通常為磁盤的一整塊, 且獨立於文件系統(交換區),使用起來很快
- 交換通常在系統有很多程序運行並且系統內存吃緊的時候執行,在系統負荷降低時就暫停
- 普通的交換使用的不多, 但交換策略的某些變體在許多系統(UNIX系統)中仍發揮作用
區別:
- 交換主要在不同的進程或作業之間
- 覆蓋則在同一個程序或進程中, 由於覆蓋技術要求給出程序段之間的覆蓋結構,對用戶和程序猿不夠透明,覆蓋已經成為歷史,現代操作系統主要通過虛擬技術來解決問題,擴充內存,交換技術也被廣泛使用。
- 關鍵字理解: 透明性, 適用時間
內存的連續分配管理方式
- 單一連續分配
- 內存中永遠只有一道程序,獨占內存,不用保護,
- 無外部碎片,
- 可以采用覆蓋技術
- 只適用於單用戶,單任務的操作系統,有內部碎片,存儲的利用率極低
- 固定分區分配
- 簡單的多道程序存儲管理方式,將用戶空間划分為若干固定大小的作區間
- 無外部碎片
- 但不能實現多進程共享一個主存區
- 很少用於現代操作系統中,在某些用於控制多個對象的控制系統中仍然發揮者一定的作用
(如: 同步並發執行10000個一摸一項的個程序,執行某項任務,如挖礦, 相同的程序,相同的功能)
- 動態分區分配:
- 不預先划分內存,而是進程裝入內存時候,根據進程的大小動態的建立分區, 並使分區的大小正好合適進程的需要,
- 系統中的分區屬木大小都是可變的
- 隨着裝入的程序越來越多,內存中會出現越來越多的小的內存塊,形成外部碎片
- 剛開始挺好的,越到后面越來越多的碎片
- 在進程裝入或換入主存時,若內存中有多個足夠大的空閑塊,則操作系統必須確定分配那個內存塊給進程使用,者就是動態分區的分配策略
- 首次適應(First Fit): 空閑分區以遞增的次序鏈接, 分配內存時按順序查找,找到能滿足要求的第一個空閑空間。 ( 地址遞增 順序查找找第一個能裝下的空間)
- 最佳適應(Best Fit): 空閑分區按照容量遞增的方式形成分區鏈, 找到第一個能夠滿足要求的空閑分區
- 最壞適應(Worst Fit): 又稱為最大適應(Largest Fit),空閑分區以容量遞減的次序鏈接,找到第一個能滿足要求的空閑區間,即挑出最大分區
- 臨近適應(Next Fit): 循環首次適應算法, 再首次算法的基礎上開始, (第二次裝入程序查找空閑分區的起始位置不同而已)
關鍵點: 對應了 數組順序查詢,鏈表頭開始查詢, 鏈表尾開始查詢, 環形鏈表一次查詢
內存非連續分配管理方式
基本的分野存儲管理方式
- 內存塊細分,減少碎片
- 進程也以塊細分,以最小塊為單位,逐個像系統申請主存中的塊空間
- 如此,每個進程只會產生大概半個頁的碎片
分頁的概念
- 進程中的塊稱為頁(Page)
- 內存中的塊稱為葉匡(Page Frame),頁幀
- 外存也以同樣的單位進行划分,直接稱為塊(Block)
- 進程在執行的時候需要申請主存空間,為每個頁面分配主存中可用的頁框,產生了頁和頁框的一一對應關系
- 頁面大小為2個整數倍,保持大小適度,過小導致換入換出頻繁,過大容易出現碎片,如macOS下通過pageSize可以查看操作系統的分頁為4kB
dart pageSize
xxxMacBook:~ xxx$ pageSize
4096 - 地址結構
- 頁號(31-12)-頁內偏移量(11-0), 4字節,32位
頁表
- 記錄內存中頁面對應的物理塊號,一表一般存儲於內存中,系統為每個進程創建了一個頁表,記錄它們在內存中對應的物理塊號
頁號 塊號 1 2 2 3 ... ...
基本的地址變換機構
- 地址的變換機構的任務是將邏輯地址轉換為內存中的物理地址,地址變換借助於頁表來實現
- 系統中通常會設置一個頁表寄存器(PTR, Page Table Register),存放頁表在內存起始地址F和頁表長度M
- 通過起始地址,頁號和相對地址很容易計算出 程序中某條相對指令地址在物理地址中絕對地址
分頁管理的問題
- 每次訪問存儲操作都需要從邏輯地址到物理地址的轉換, 地址轉換必須足夠快
- 每個進程引入頁表,用於存儲進程的內存映射機制,頁表不能太大
具有快表地址變換機構
- 通過上面的地址變化過程可知,若頁表全部放入內存中,則存取一個數據或一條指令至少需要訪問兩次內存,第一次是訪問頁表,第二區定所存儲數據或者指令的物理地址,第二次是根據該地址存取數據或指令,這種方式比普通的執行指令減慢了一半
- 為此,在地址變換機構中增設一個具有並行查找能力的告訴緩沖存儲器---快表,又稱為相聯存儲器(TLB),用來存儲當前訪問的若干頁表項,以加速地址變換過程.與此對應,主存中的頁表項常稱為慢表.
快表的實現:
在具有快表分頁機制中,地址的變換過程如下- CPU給出地址邏輯之后, 由硬件地址進行地址轉換, 將也好送入告訴緩沖存儲器,並將此頁號與快表中的所有也號進行比較
- 若找到匹配的頁號,說明需要訪問的頁表項在快表中,則直接從中取出對應的頁框號,與頁內偏移量拼接形成物理地址.
- 若未找到匹配的頁號, 則需要訪問主存中的頁表,在讀取頁表以后,同時將其存入到快表中,以便以后能快速訪問, 若快表已滿,則需要按照一定的規則和算法對舊的頁表項進行替換。 (一般快表的命中率達90%以上,這樣分頁帶來的損失就可以下降到10%以下)
兩級頁表
- 由於引入了分頁管理,進程在執行時不需要將所有頁調入內存頁框,只需要將保存有映射關系的頁表調入內存,但仍需要考慮頁表的大小 *****
為了壓縮頁表項,我們進一步延伸頁表映射的思想,就可以得到二級分頁。
一級頁號 二級頁號 頁內偏移量
基於分段存儲管理方式
- 分頁的管理方式是從計算機角度來考慮設計的,提高計算器的利用率和性能,分頁通過硬件機制實現,對用戶完全透明,
- 分段管理方式則是考慮了用戶和程序猿,以滿足編程,信號保護和共享,動態增長和動態鏈接等多方面的需要(segment)
分段
- 段的管理方式按照用戶進程中的自然段划分邏輯空間,例如用戶進程由主程序,兩個子程序,棧和一段數據組成,於是可以把這個用戶進程划分為5段, 每段從0開始編址,並分配一段連續的地址空間(段內要求連續,段間不要求連續,因此整個作業的地址空間是二位的),其邏輯地址由段號S與段內偏移量W組成. 216 = 65536, 一個作業最多有這么多段, 由編譯程序完成
|31 .... 16 | 15 ... 0 |
|------|------|
| 段號 | 段內偏移量 |
- 段的管理方式按照用戶進程中的自然段划分邏輯空間,例如用戶進程由主程序,兩個子程序,棧和一段數據組成,於是可以把這個用戶進程划分為5段, 每段從0開始編址,並分配一段連續的地址空間(段內要求連續,段間不要求連續,因此整個作業的地址空間是二位的),其邏輯地址由段號S與段內偏移量W組成. 216 = 65536, 一個作業最多有這么多段, 由編譯程序完成
段表
- 每個進程都有一張邏輯空間與內存空間映射的段表,其中每個段表項對應進程的一段,段表記錄該段在內存中的始址和長度,段表的內容如下
|段號|段長|本段主存的始址|
|---|---|---|
段表也是用來實現從邏輯段到物理內存區的映射 - 地址變化機構
- 同樣的在系統中也設置了段表的寄存器,用來存放段的起始位置F和段表長度M
- 每個進程都有一張邏輯空間與內存空間映射的段表,其中每個段表項對應進程的一段,段表記錄該段在內存中的始址和長度,段表的內容如下
段的共享和保護
- 通過兩個作業的段表中相應的表項只想共享的段的痛一個物理副本中的數據。
- 與分頁類似: 通過存取控制保護, 地址越界保護
- 與頁式管理不同,段式管理不能夠通過給出一個整數便確定對應的物理地址,因為每段的長度不是固定的
段頁的管理
段號 -> 頁號 -> 頁內偏移量 **** 補充
虛擬內存管理
- 傳統的內存管理基本概念
- 一次性
- 駐留性
- 局部性原理
- 快表,頁高速緩存及虛擬內存技術從廣義上講,都屬於高速緩沖技術,這個技術依賴於 局部性原理.
- 時間局部性: 存儲將要執行的指令,如循環,
- 空間局不性: 如數組,順序保存數據, 保存到高速緩沖器中
- 虛擬存儲器的定義和特征
- 多次性 分多次調入內存
- 對換性 換入換出,不用常駐
- 虛擬性 內存容量遠大於實際的內存容量
虛擬內存技術的實現
- 虛擬內存的實現建立在離散分配的內存管理方式基礎上
- 請求分頁存儲管理
- 請求分段存儲管理
- 請求段頁存儲管理
- 一定容量的內存和外存
- 頁表機制
- 中斷機構 (用戶要訪問的數據未調入內存時,則產生中斷)
- 地址變換機構 邏輯地址到物理地址轉換
- 虛擬內存的實現建立在離散分配的內存管理方式基礎上
請求分頁管理方式
- 頁表機制
|頁號| 物理塊號| 狀態位置P| 訪問字段A | 修改位M |外存地址|
|--- | --- | --- | --- |---| ---| - 狀態位: 用於指示該頁是否已調入內存
- 訪問字段A: 用於記錄該頁面在一段時間內被訪問的次數
- 修改位M: 標示該頁在調入內存后是否修改過
- 外存地址: 用於指出改頁在外存上的地址,通常是物理塊號,供調入時參考
- 頁表機制
缺頁中斷機構
- 在指令執行期間而非一條指令執行完成后產生和處理中斷信號屬於內部中斷
- 在一條指令缺失過程中,可能會產生多次的缺頁中斷
地址變化機構
- 若找到要訪問的頁,則修改頁表像中的訪問位,然后利用頁表給出的物理塊號和頁內地址形成的物理地址
- 若未找到改頁的頁表項,則應到內存中查找頁表,再比較頁表項中的狀態位P,若未調入內存則產生缺頁中斷,調入內存
頁面置換算法
- 最佳置換算法(OPT): Optimal,淘汰以后永不使用或者最長時間不被訪問
- FIFO: 先進先出,不夠靈活,缺頁故障更明顯 bug
- LRU: 最近最久未使用
- CLOCK: 時鍾算法, 時鍾循環檢查, 標志位,是否寫入,優先淘汰未寫入,未訪問的 -> (1,1) -> ..
頁面分配策略
- 駐留集大小:
- 分配給一個進程的存儲量越小,任何時候駐留在主存中的進程數就越多,從而可以提高處理機時間利用效率
- 若一個進程在主存中的頁數過小,則盡管有局部性原理,頁錯誤率依然很高
- 若頁數過多,則由於局不性原理,給特定進程分配更多的主存空間對該進程的錯誤率並沒有明顯的影響
- 三種分配策略
- 固定分配局部置換: 分配固定數目的物理塊,若缺頁,則從該進程所在的內存頁面中選出一頁置換
- 固定分配全局置換: 同上,從操作系統的物理塊隊列中取出一個物理塊分配給該進程, 若盲目添加也會帶來弊端
- 可變換局部置換: 分配初始的進程塊,當缺頁時先從該進程中置換,若一段時間缺頁率高,由系統分配新的物理塊,反之則回收部分物理塊
- 調入頁面的時機
- 預調入: 如啟動,目前越%50的命中率, 可以通過對啟動經常調用的方法符號重排,減少跨頁訪問,節省啟動時間,
- 請求調頁策略
- 從何處調入頁面
- 系統擁有足夠的對換區空間
- 系統缺少足夠的對換空間
- UNIX方式: 與進程相關文件都放在文件區,未運行的頁面都需要從文件區調入
抖動
- 剛剛換出的頁面馬上又被換入
- 主要原因: 某個進程頻繁訪問的頁面數目高於可用的物理頁幀數目
工作集
- 在某段時間內,進程訪問的頁面集合,基於局部性原理,可以用最近訪問的頁面來確定工作集,動態分配和回收內存塊,避免抖動
地址翻譯
- TODO: