# 作業系統CH9 Virtual Memory Management ###### tags: `作業系統 Operating System` ## Background - 為何我們不希望執行 program 時,將所有內容放進 memory 中 - 有許多程式碼負責不常使用的 erros 或 conditions - 部份 program routine 不常使用 - 很多 program 使用相同的 library - 已經配置但沒有被使用的 Arrays, lists & tables - 我們希望更好的 memory 使用率,真的需要使用的才放入 memory 中 - Virtual memory: 將 user logical memory 從 physical memory 分離 - 因為 logical -> physical 只是 mapping 的問題,所以 logical memory 可以比 physical memory 來的大,可以執行非常大的 process - 提高 CPU/resources 的使用率,越多 process 在 virtual memory 中,degree 越高,就越容易找到需要某個資源的 process 去使用 - 簡化 compiling 的工作,不需要管 memory 的限制 - 提昇 programs 的執行速度,因為不用將整個 program 讀進 memory,有較低的 I/O load & swap 的負載 - Virtual memory 可以透過以下兩種方式實作 - Demand paging,因為是 fix-size,對硬體使用來說資源分配比較容易管理 - Demand segmentation -> 因 segmentation 大小不固定,要找到空間的複雜度較高,效率較低,但對 user 來說比較容易理解及使用 (heap, stack...etc) - Virtual Memory vs. Physical Memory ![](https://i.imgur.com/SpkNHOm.png) ## Demand Paging ### Demand Paging - 當 Page 被需要時才讀進 memory 中,好處是 - 較少的 I/O 需求 --> 更快的響應 - 較少的 memory 需求 --> 可以有更多 programs 執行 - 當 Page 有 reference 指向它時,代表 Page 被需要 - 若 reference invalid --> abort (沒有 allocate) - Not-in-memory --> 利用 paging 讀入記憶體 (page fault) - pure demand paging - process 啟動時完全沒有 page - 只有當 page 需要時才讀進 memory - swapper (midterm scheduler) 管理整個 process ,而 pager 則是管理 process 的一個 page 為單位 - 硬體支援 - Page Table: valid-invalid bit 來表示 page 是否在記憶體中 - 1 -> page in memory - 0 -> page not in memory - 一開始該 bits 都設成 0 - Secondary memory (swap space, backing store): page 從 memory 被 swap 出去的儲存空間,通常是 high-speed disk ### Page Fault 相關資料:[MIT6.s081 Lab: xv6 lazy page allocation](https://hackmd.io/@Chang-Chia-Chi/SyVVrPBRt) - 第一次的 reference 會引發 trap to OS - 稱為 page fault trap 1. OS 會查看在 PCB 裡頭的 internal table ,確認是 Invalid 或只是 not in memory,決定後續動作 2. 找到一個 empty frame (可以置放 page 的空間) 3. 將 page 從 disk (swap space) 移到 frame 4. 設定 Page-table,將 valid-invalid bit 設為 1 5. 重啟 instruction ![](https://i.imgur.com/84jRsLy.png) ### Page Replacement - 若 page fault 時沒有 free frame 的話 - Swap 一個 frame 回 backing store - Swap 目標 page 進 frame ### Demand Paging Performance - Effective Access Time (EAT): $(1-p) * ma + p * pft$ - p 為 page fault rate, ma 為 mem. access time, pft 為 page fault time - mem. access time 包含找到位置及將資料從 memory chip 搬到 CPU register 的時間 - page fault time 則多了資料在記憶體 - disk 之間 swap 的時間 - pft 遠大於 ma,EAT 基本上由 pft 及 page fault rate 決定 - 假設 ma = 200 ns, pft = 8 ms,若 1000 次產生 1 次 page fault,則速度就會慢上 40 倍 ; 換個角度如果我們希望 page fault 對讀取時間的影響小於 10%,則 page fault rate 必須小於 0.0000025 - Programs 的 refernce 通常是 locality 的,代表 program 通常會存取在鄰近位置的 memory address - 一個 page fault 可以讀取 4KB 的資料進來 - 大幅降低 page fault 發生的機率 - Page fault time 的時間組成 1. page-fault 中斷 2. 將 page 從 disk 中讀進 memory (最花時間) 3. 重啟 process ## Process Creation ### Process & Virtual Memory - Demand Paging: 當有需要時才 swap page 進 memory - Copy-on-Write: parent 跟 child processes 一開始共享 frames,當有內容發生不同時,才會 copy frame - Memory-Mapped File: 將 file 的 disk content 當作 memory content,用 virtual address space 做 mapping,避開 file system,增加 I/O 效能。通常適用於大檔案,因為 paging 需要 4KB 的空間,小檔案使用會有記憶體空間碎片化的問題 ### Copy-on-Write 相關資料:[MIT6.s081 Lab: Copy-on-Write Fork for xv6](https://hackmd.io/@Chang-Chia-Chi/BkMAP0Hk5) - 允許 parent & child 共享 frames - 若其中一者變更 frame,則僅對該 frame 進行 copy 的動作 - COW 使得 process creation 有效率(e.g. fork()) - 通常 free frame 時會完全清空,避免前一個 process 使用的一些 content 被其他 process 看見,造成潛在的安全性問題 - When a child process is forked ![](https://i.imgur.com/Qo1XVaA.png) - After a page is modified ![](https://i.imgur.com/0jt22um.png) ### Memory-Mapped Files - 方法: - MMF 透過 disk block to memory frame 的 mapping,讓 I/O 像一般的記憶體存取,略過 file system calls (eg. read(), write()) - file 一開始使用 demand paging 讀取,之後的讀寫動作視作一般的 memory access - 好處: - 略過 file system calls (如 read(), write()) - 允許多個 processes 共享 file 的內容 - 壞處: - 安全性、資料遺失、更多的 programming efforts - 範例: ![](https://i.imgur.com/bsYuJyI.png) ## Page Replacement Page Replacement 的演算法會嚴重影響系統的速度,假設演算法經常將需要用到的 pages swap 去 disk,則 pages 在 memory 跟 disk 一直來回的時間會大幅拖慢系統的效能 ### Page Replacement Concept - 當沒有 free frame 時發生 page fault - 將整個 process swap 掉,釋放所有 process 佔有的 free frames,但這樣 process 就完全不能使用,並不是一個好方法 - 採用 page replacement ,找到一個目前沒有被使用的 frame 將其 free 掉 - 使用 dirty bit 表示 page 的內容是否被修改過,若 page 沒有被修改過,就直接 free 掉 frame 的內容; 有修改過才將資料寫回 disk ,來減少 page transfers 的 overhead, - replacement 必須要處理兩個問題 - free-allocation algorithm: 演算法必須決定多少 frames 應該 allocate 給 process - page-replacement algorithm: 選擇哪些 frames 被取代 ### Page Replacement Step 1. 在 disk 中找到需要的 page 2. 若有 free frame,則直接使用; 若沒有 free frame 則執行 page replacement 演算法來選擇被取代的 frame 3. 將需求的 page 讀進 free frame 中,並更新 page & frame tables 4. 重啟 process 的指令 ### Page Replacement Algorithms - 目標:最低的 page-fault rate - 評估:一連串的 page id (reference string, memory refernces) 為輸入,計算 page fault 發生的次數 #### FIFO algorithm - 在佇列中最舊的 page 會被取代 - 範例: - 假設 available memory frames = 3 - 產生 9 次 page fault ![](https://i.imgur.com/bjgRBP9.png) - Belady's Anomaly: 即便增加 frames 的數量,page fault 的數量不一定會減少,還有可能會增加 - 假設 available memory frames = 4 - 產生 10 次 page fault ![](https://i.imgur.com/m2Uivap.png) - 因為 Belady's Anomaly,使得我們很難對系統進行調整,例如插越多條記憶體,反而執行速度有機會變慢 #### Optimal (Belady) Algorithm - 取代未來最長時間不會被使用的 page - 但實際上我們不會有未來的資訊 - 因此這個演算法比較類似提供我們一個基準 ![](https://i.imgur.com/Zt8FZzm.png) #### LRU Algorithm (Least Recently Used) - 一種 optimal algorithm 的近似 - 因為無法預測未來,所以我們往回看 - 取代最長時間沒有被使用的 page - 因為 locality 及時間複雜度低(O(1))的緣故,LRU 很常被使用 - Counter implementation - 紀錄每個 page 最近被使用的 time-stamp - 取代 time-stamp 最舊的 page - 時間複雜度 O(N) - Stack implementation (實際使用) - 當 page 被使用時,將 page 移到 double-linked list 最前方 - 可以用 hash map 紀錄 double-linked list 每個 element 的指標,達成 O(1) 的實作 - 取代 linked list 中位在 tail 的 page ![](https://i.imgur.com/pp2AitH.png) #### Stack Algorithm Optimal & LRU 都是 stack algorithm,有以下這些特性 - n frames 的 pages 一定是 n+1 frames pages 的 subset,也就是說因為 stack 的特性,先被放入的元素一定會先被看到,若增加 frames,也只是在原 stack 後面增加一些 pages 而已 - Stack algorithm 不會有 Belady's anomaly 問題 #### LRU 近似的演算法 - additional-reference-bits algorithm - second-chance algorithm:2 個 LRU stack - enhanced second-chance algorithm #### Counting Algorithms - LFU Algorithm (least frequently used) - 每一個 page 有 counter - 經常被使用的 page 應該要有大的 count value - MFU Algorithm (most frequently used) - 不過常用不代表正在用,有可能在某些時刻集中使用,將 count 拉高,但多數時間沒有使用 - 最小的 count 有可能是剛帶進來的,還沒被使用,所以應該留著 - 兩者都不常用 - 要一直執行加法成本很高 - 有 overflow 的問題 - 表現不一定較佳 ## Allocation of frames 每個 process 最少都需要一定數量的 frames ### Frame Allocation - Fixed allocation: 根據 process 在一開始就決定要 allocate 多少 frame - Equal allocation: 每個 process 配置到的 frames 數目相同 - Proportional allocation: 根據 process 的大小來配置 - Priority allocation - 在 run time 的時候,根據 process 的優先度決定配置 - 如果 process 發生 page fault - 選擇 process 本身的一個 frame 來替代 - 或著選擇低優先度的 process 的 frame 來替代 - Local allocation: 只能替換自己的 frames,通常跟 fixed allocation 綁在一起 - Global allocation: 從所有的 frames 中選擇一個來替代 - 可以拿其他 process 的 frame - 例如讓高優先度的 process 搶低優先度的 process - 有好的系統表現,所以較常使用 - 會有一個問題是如果一直搶低優先度 process 的 frame,有可能該 process 甚至無法維持最低的 frames 數量,所以要有機制來維持最低 frames,避免 process 被 thrashing ## Thrashing 如果一個 process 沒有足夠的 frames,代表 process 在記憶體中的 frames 數量不足以支撐 process 執行,導致 page fault 一直在發生 (且 page fault 是 instruction level,無法 overlap),等於 CPU 要一直等待 I/O,造成 CPU 使用率反而下降的情況 - Thrashing 的定義為: 當一個 process 花在 paging 的時間比執行時間更高時,稱為 thrashing ![](https://i.imgur.com/ZkHI6EB.png) - Thrashing 造成的 performance 問題 - processes 因 page fault 在等待 I/O - 因此 CPU 使用率下降 - OS 發現 CPU 使用率下降,增加 degree of multiprogramming - 新產生的 processes 從舊的 processes 搶 frames,導致更多的 page fault - 結果 CPU 的使用率繼續下降 - 為了避免 Thrashing,必須要控制 degree of multiprogramming ### Working-Set Model - 從 Locality 的角度思考,對一個 process 而言,我們可以計算在這段時間內使用多少 pages,這個數量就是要 assign 給 process 的 frames 數量 - 因為 process 的需求是動態變化的,所以 locality 會隨時間改變,OS 必須要持續追蹤 processes 的 locality - 例如 program structure (如 subroutine, loop, stack) - 或 data structure (array, table...etc) - Working-set Model - Working-set window: 觀察的一段時間 - Working-set size: 這一段時間內,被 process reference 到的 page 數 ![](https://i.imgur.com/7qnK5BT.png) - 每一個 process 的 working set size $WSS_i$ - frames 的總需求數 $D = ∑ WSS_i$ - 如果 D > m (available frames) ,則有 thrashing 發生 - OS 會監控每個 process 的 $WSS_i$,並配置足夠的 frames 給每個 process - 如果 D << m,增加 degree of multiprogramming - 如果 D > m,把整個 process suspend (mid-term scheduler) 掉,free 該 process 所有的 frames - 優點 1. 在最大化 multiprogramming 的情況下,同時防止 thrashing 的發生 2. 可以最大化 CPU 使用率 - 缺點 1. tracking 的成本很高 ### Page Fault Frequency Scheme - 監控每個 process 發生 page fault 的機率,控制 page fault rate 在一定範圍內來防止 thrashing 的現象 - 依據 page fault rate 為每一個 process 建立 upper 跟 lower bounds - 如果 page fault rate 超過 upper limit,則配置更多的 frames - 如果 page fault rate 低於 lower limit,則移除部份的 frames ![](https://i.imgur.com/ryZQALs.png) ### Working Sets and Page Fault Rates 重點是 memory 的 locality 會變化,所以需要追蹤 process 的使用情況,動態地調整 processes 及 frames 的配置情況 ![](https://i.imgur.com/9HJUwpn.png) ## Reference 1. [清大開放課程 - 作業系統](https://www.youtube.com/watch?v=aK0_PBLWCAM&list=PL9jciz8qz_zyO55qECi2PD3k6lgxluYEV&index=38) 2. [Operating System Concept 9th edition](https://www.os-book.com/OS9/slide-dir/index.html)