想和你聊聊操作系統(tǒng)的內(nèi)存管理
本文轉(zhuǎn)載自微信公眾號「java小杰要加油」,作者好懂事一男的。轉(zhuǎn)載本文請聯(lián)系java小杰要加油公眾號。
物理地址 VS 虛擬地址
- 物理地址:邏輯上,我們可以把物理內(nèi)存看成一個大數(shù)組,其中每個字節(jié)都可以通過與之對應(yīng)的地址進行訪問,這個地址就叫做物理地址
- 虛擬地址 :應(yīng)用程序在運行時使用的地址
CPU翻譯虛擬地址的過程大概如圖所示
他們的包含關(guān)系如下:cpu包含MMU,MMU包含TLB
- CPU
- TLB(轉(zhuǎn)址旁路緩存 Translation Lookaside Buffer):加速地址翻譯的過程
- MMU(內(nèi)存管理單元 Memory Management Unit): 負責(zé)虛擬地址到物理地址的轉(zhuǎn)換
平常加載程序的順序是
- 操作系統(tǒng)把程序從磁盤加載到內(nèi)存中(程序一開始是在磁盤中存放的)
- CPU去執(zhí)行程序的第一條指令但是這個指令現(xiàn)在在物理內(nèi)存中
- cpu取指令取的是該指令的虛擬地址,由MMU翻譯為物理地址
- 這個讀物理地址的請求將通過總線,傳送到相應(yīng)的物理內(nèi)存中,然后物理內(nèi)存把該指令發(fā)送給CPU
分段
“MMU將虛擬地址翻譯為物理地址主要有兩種機制 :分段和分頁
分段機制
- 操作系統(tǒng)以“段”(一段連續(xù)的物理內(nèi)存)的形式管理/分配物理內(nèi)存
- 應(yīng)用程序的虛擬地址空間由若干個大小不同的段組成:代碼段、數(shù)據(jù)段等等
- 當(dāng)CPU訪問虛擬地址中的某一個段的時候,MMU會通過查詢段表來得到該段對應(yīng)的物理地址
虛擬地址:
- 段號: 標志著該虛擬地址屬于整個虛擬地址空間中的哪一段
- 段內(nèi)地址(段內(nèi)偏移): 相對于該段起始地址的偏移量
“當(dāng) cpu 讀取指令時,發(fā)現(xiàn)指令的地址是虛擬地址,那么CPU中的MMU 首先判斷這個段號是否合法,如果合法, 則通過 段表基址寄存器 找到段表的位置,通過虛擬地址中的段號,找到該段的起始地址,再加上段內(nèi)地址(段內(nèi)偏移),就可以得到最終的物理地址
在分段機制下,虛擬內(nèi)存和物理內(nèi)存都劃分成了不同的段
分段缺點
- 在虛擬地址空間中,相鄰的段所對應(yīng)的物理內(nèi)存空間可以不相鄰,操作系統(tǒng)能夠?qū)崿F(xiàn)物理內(nèi)存資源的離散分配,但是這種段式分配方式容易導(dǎo)致在物理內(nèi)存上出現(xiàn)外部碎片
圖中裝載不進來的就是外部碎片
分頁機制
- 基本思想:
- 將應(yīng)用程序的虛擬地址空間劃分為連續(xù)的、等長的虛擬頁(4K)
- 物理地址也是劃分為連續(xù)的、等長的的物理頁
- 物理頁和虛擬頁頁長固定且相等
之所以這樣構(gòu)造是因為會使操作系統(tǒng)很方便的為每個應(yīng)用程序構(gòu)造頁表,即虛擬頁和物理頁映射關(guān)系表
- 在分頁機制下,應(yīng)用程序虛擬地址空間中的任意虛擬頁可以被映射到物理內(nèi)存中的任意物理頁上,可以避免外部碎片的問題
- 分頁機制下的虛擬地址也由兩部分組成:虛擬頁號: 頁內(nèi)偏移量:
翻譯的具體流程就是:
- MMU首先解析虛擬地址中的虛擬頁號,檢查這個虛擬頁號是否合法,通過這個虛擬頁號取該應(yīng)用程序的虛擬頁表中找到對應(yīng)條目(頁表起始地址放在頁表基地址寄存器)
- 然后取出該條目中的物理頁號
- 最后用該物理頁號對應(yīng)的物理起始地址加上虛擬地址中的頁內(nèi)偏移得到最終的物理地址
TLB
首先要說一下局部性原理
- 時間局部性: 如果執(zhí)行了程序中的某條指令,那么不久后這條指令很有可能再次執(zhí)行,如果某個數(shù)據(jù)被訪問過,不久后該數(shù)據(jù)很可能再次被訪問(因為程序中存在大量的循環(huán))
- 空間局部性: 一旦程序訪問了某個存儲單元,在不久之后,其附近的存儲單元也很有可能會被訪問(因為很多數(shù)據(jù)在內(nèi)存中都是連續(xù)存放的)
所以,能不能弄一個緩存,緩存這些有可能會被經(jīng)常被訪問的數(shù)據(jù)呢,從而減少訪問頁表的次數(shù)呢?
為了減少地址翻譯的訪問次數(shù),MMU引入TLB(轉(zhuǎn)址旁路緩存 Translation Lookaside Buffer)
- TLB 硬件采用分層架構(gòu),分為L1、L2兩層。
- LI又分為數(shù)據(jù)TLB和指令TLB,分別緩存數(shù)據(jù)和指令的地址翻譯
- L2不區(qū)分數(shù)據(jù)和指令
- TLB緩存了虛擬頁號和物理頁號的映射關(guān)系,類似map,key是虛擬頁號,value是物理頁號。
- 如果在TLB中找到則稱為TLB命中
- 沒有找到則稱之為TLB未命中
“有了TLB之后,查詢就變成了
1. MMU首先解析虛擬地址中的虛擬頁號,檢查這個虛擬頁號是否合法,如果合法
- 查TLB,如果命中則 直接取出物理初始地址,再加上頁內(nèi)偏移量得到最終物理地址,否則繼續(xù)查詢頁表
- 如果頁表中存在物理初始地址,則將此物理初始地址緩存到TLB中 通過這個虛擬頁號取該應(yīng)用程序的虛擬頁表中找到對應(yīng)條目(頁表起始地址放在頁表基地址寄存器)
然后取出該條目中的物理頁號
最后用該物理頁號對應(yīng)的物理起始地址加上虛擬地址中的頁內(nèi)偏移得到最終的物理地址
多級頁表
- 如果頁表太大時怎么辦,頁表必須連續(xù)存放,會占用很多內(nèi)存,所以就把一個大表拆成很多小表
拆分后的訪問順序如圖所示
- 根據(jù)一級頁號查找到物理頁號,這個物理頁號里面裝的是二級頁表的地址,找到此地址后,在根據(jù)二級頁號 找到物理地址,此物理地址在加上頁內(nèi)偏移量則為最終的物理地址
換頁與缺頁異常
換頁
“虛擬內(nèi)存中的換頁:當(dāng)物理內(nèi)存容量不夠的時候,操作系統(tǒng)應(yīng)當(dāng)把若干物理頁的內(nèi)容寫到磁盤這種大容量的地方,然后回收物理頁并繼續(xù)使用
舉例:有個應(yīng)用程序A,A的虛擬頁K對應(yīng)物理頁V,這個時候,操作系統(tǒng)想回收物理頁V,要怎么做呢?
- 操作系統(tǒng)把V寫到磁盤上
- 并且在A的頁表中除去虛擬頁K和物理頁V的映射,同時記錄物理頁V被換到磁盤上的對應(yīng)的位置
以上這兩部被稱為物理頁V的換出
缺頁異常
缺頁異常是換頁機制能夠工作的前提,當(dāng)應(yīng)用程序訪問已經(jīng)分配但是未映射至物理內(nèi)存的虛擬頁時,就會觸發(fā)缺頁異常
- 如何解決:通過換入
- cpu會運行操作系統(tǒng)預(yù)先設(shè)置的缺頁異常處理函數(shù),該函數(shù)會找到一個空閑的物理頁,
- 將以前寫入到磁盤上的內(nèi)容重新加載到該空閑的物理頁
- 然后將虛擬地址和此物理地址映射起來
處理完這一切后,cpu回到發(fā)生缺頁異常的地方繼續(xù)運行
段頁式內(nèi)存管理
分段管理
- 優(yōu)點: 很方便的按照邏輯模塊實現(xiàn)信息的共享和保護
- 缺點: 容易產(chǎn)生外部碎片
分頁管理
- 優(yōu)點 內(nèi)存空間利用率高,不會產(chǎn)生外部碎片,只會有少量頁內(nèi)碎片
- 缺點: 不方便按照邏輯模塊實現(xiàn)信息的共享和保護
段頁式內(nèi)存管理
- 將地址空間按照程序自身的邏輯關(guān)系分為若干層,將各段分為大小相等的頁面
- 將物理內(nèi)存與虛擬內(nèi)存劃分為大小相等的一個個的內(nèi)存塊,系統(tǒng)以塊為單位為進程分配內(nèi)存
- 邏輯地址/虛擬地址(段號,頁號,頁內(nèi)偏移量)
虛擬地址翻譯為物理地址的步驟變?yōu)?/p>
- 根據(jù)邏輯地址取出其中的段號,判斷這個段號是否正常
- 如果正常,則找到該段號對應(yīng)的頁表初始地址
- 根據(jù)頁號是否正常,若正常則根據(jù)頁號找到物理初始地址,在加上頁內(nèi)偏移量則找到真正的物理地址
原文鏈接:https://mp.weixin.qq.com/s/miq1GTn9xn9oKY-fYBiYDQ