虛擬內存是什么意思 - 虛擬內存原理與工作方式(2/2)
TLB 通常位于 MMU 中,包含少量的表項,每個表項都記錄了頁面的相關信息,除了虛擬頁號外,其他表項都和頁表是一一對應的
是不是你到現在還是有點不理解什么是 TLB,TLB 其實就是一種內存緩存,用于減少訪問內存所需要的時間,它就是 MMU 的一部分,TLB 會將虛擬地址到物理地址的轉換存儲起來,通常可以稱為地址翻譯緩存(address-translation cache)。TLB 通常位于 CPU 和 CPU 緩存之間,它與 CPU 緩存是不同的緩存級別。下面我們來看一下 TLB 是如何工作的。
當一個 MMU 中的虛擬地址需要進行轉換時,硬件首先檢查虛擬頁號與 TLB 中所有表項進行并行匹配,判斷虛擬頁是否在 TLB 中。如果找到了有效匹配項,并且要進行的訪問操作沒有違反保護位的話,則將頁框號直接從 TLB 中取出而不用再直接訪問頁表。如果虛擬頁在 TLB 中但是違反了保護位的權限的話(比如只允許讀但是是一個寫指令),則會生成一個保護錯誤(protection fault)返回。
上面探討的是虛擬地址在 TLB 中的情況,那么如果虛擬地址不再 TLB 中該怎么辦?如果 MMU 檢測到沒有有效的匹配項,就會進行正常的頁表查找,然后從 TLB 中逐出一個表項然后把從頁表中找到的項放在 TLB 中。當一個表項被從 TLB 中清除出,將修改位復制到內存中頁表項,除了訪問位之外,其他位保持不變。當頁表項從頁表裝入 TLB 中時,所有的值都來自于內存。
軟件 TLB 管理
直到現在,我們假設每臺電腦都有可以被硬件識別的頁表,外加一個 TLB。在這個設計中,TLB 管理和處理 TLB 錯誤完全由硬件來完成。僅僅當頁面不在內存中時,才會發生操作系統的陷入(trap)。
在以前,我們上面的假設通常是正確的。但是,許多現代的 RISC 機器,包括 SPARC、MIPS 和 HP PA,幾乎所有的頁面管理都是在軟件中完成的。
精簡指令集計算機或 RISC 是一種計算機指令集,它使計算機的微處理器的每條指令(CPI)周期比復雜指令集計算機(CISC)少
在這些計算機上,TLB 條目由操作系統顯示加載。當發生 TLB 訪問丟失時,不再是由 MMU 到頁表中查找并取出需要的頁表項,而是生成一個 TLB 失效并將問題交給操作系統解決。操作系統必須找到該頁,把它從 TLB 中移除(移除頁表中的一項),然后把新找到的頁放在 TLB 中,最后再執行先前出錯的指令。然而,所有這些操作都必須通過少量指令完成,因為 TLB 丟失的發生率要比出錯率高很多。
無論是用硬件還是用軟件來處理 TLB 失效,常見的方式都是找到頁表并執行索引操作以定位到將要訪問的頁面,在軟件中進行搜索的問題是保存頁表的頁可能不在 TLB 中,這將在處理過程中導致其他 TLB 錯誤。改善方法是可以在內存中的固定位置維護一個大的 TLB 表項的高速緩存來減少 TLB 失效。通過首先檢查軟件的高速緩存,操作系統 能夠有效的減少 TLB 失效問題。
TLB 軟件管理會有兩種 TLB 失效問題,當一個頁訪問在內存中而不在 TLB 中時,將產生 軟失效(soft miss),那么此時要做的就是把頁表更新到 TLB 中(我們上面探討的過程),而不會產生磁盤 I/O,處理僅僅需要一些機器指令在幾納秒的時間內完成。然而,當頁本身不在內存中時,將會產生硬失效(hard miss),那么此時就需要從磁盤中進行頁表提取,硬失效的處理時間通常是軟失效的百萬倍。在頁表結構中查找映射的過程稱為 頁表遍歷(page table walk)。
上面的這兩種情況都是理想情況下出現的現象,但是在實際應用過程中情況會更加復雜,未命中的情況可能既不是硬失效又不是軟失效。一些未命中可能更軟或更硬(偷笑)。比如,如果頁表遍歷的過程中沒有找到所需要的頁,那么此時會出現三種情況:
- 所需的頁面就在內存中,但是卻沒有記錄在進程的頁表中,這種情況可能是由其他進程從磁盤掉入內存,這種情況只需要把頁正確映射就可以了,而不需要在從硬盤調入,這是一種軟失效,稱為 次要缺頁錯誤(minor page fault)。
- 基于上述情況,如果需要從硬盤直接調入頁面,這就是嚴重缺頁錯誤(major page falut)。
- 還有一種情況是,程序可能訪問了一個非法地址,根本無需向 TLB 中增加映射。此時,操作系統會報告一個 段錯誤(segmentation fault) 來終止程序。只有第三種缺頁屬于程序錯誤,其他缺頁情況都會被硬件或操作系統以降低程序性能為代價來修復
針對大內存的頁表
還記得我們討論的是什么問題嗎?(捂臉),可能討論的太多你有所不知道了,我再提醒你一下,上面加速分頁過程討論的是虛擬地址到物理地址的映射速度必須要快的問題,還有一個問題是 如果虛擬地址空間足夠大,那么頁表也會足夠大的問題,如何處理巨大的虛擬地址空間,下面展開我們的討論。
多級頁表
第一種方案是使用多級頁表(multi),下面是一個例子
32 位的虛擬地址被劃分為 10 位的 PT1 域,10 位的 PT2 域,還有 12 位的 Offset 域。因為偏移量是 12 位,所以頁面大小是 4KB,共有 2^20 次方個頁面。
引入多級頁表的原因是避免把全部頁表一直保存在內存中。不需要的頁表就不應該保留。
多級頁表是一種分頁方案,它由兩個或多個層次的分頁表組成,也稱為分層分頁。級別1(level 1)頁面表的條目是指向級別 2(level 2) 頁面表的指針,級別2頁面表的條目是指向級別 3(level 3) 頁面表的指針,依此類推。最后一級頁表存儲的是實際的信息。
下面是一個二級頁表的工作過程
在最左邊是頂級頁表,它有 1024 個表項,對應于 10 位的 PT1 域。當一個虛擬地址被送到 MMU 時,MMU 首先提取 PT1 域并把該值作為訪問頂級頁表的索引。因為整個 4 GB (即 32 位)虛擬地址已經按 4 KB 大小分塊,所以頂級頁表中的 1024 個表項的每一個都表示 4M 的塊地址范圍。
由索引頂級頁表得到的表項中含有二級頁表的地址或頁框號。頂級頁表的表項 0 指向程序正文的頁表,表項 1 指向含有數據的頁表,表項 1023 指向堆棧的頁表,其他的項(用陰影表示)表示沒有使用。現在把 PT2 域作為訪問選定的二級頁表的索引,以便找到虛擬頁面的對應頁框號。
倒排頁表
針對分頁層級結構中不斷增加的替代方法是使用 倒排頁表(inverted page tables)。采用這種解決方案的有 PowerPC、UltraSPARC 和 Itanium。在這種設計中,實際內存中的每個頁框對應一個表項,而不是每個虛擬頁面對應一個表項。
雖然倒排頁表節省了大量的空間,但是它也有自己的缺陷:那就是從虛擬地址到物理地址的轉換會變得很困難。當進程 n 訪問虛擬頁面 p 時,硬件不能再通過把 p 當作指向頁表的一個索引來查找物理頁。而是必須搜索整個倒排表來查找某個表項。另外,搜索必須對每一個內存訪問操作都執行一次,而不是在發生缺頁中斷時執行。
解決這一問題的方式是使用 TLB。當發生 TLB 失效時,需要用軟件搜索整個倒排頁表。一個可行的方式是建立一個散列表,用虛擬地址來散列。當前所有內存中的具有相同散列值的虛擬頁面被鏈接在一起。如下圖所示
如果散列表中的槽數與機器中物理頁面數一樣多,那么散列表的沖突鏈的長度將會是 1 個表項的長度,這將會大大提高映射速度。一旦頁框被找到,新的(虛擬頁號,物理頁框號)就會被裝在到 TLB 中。
刊誤
P115 頁,兩條線位置畫反,根據下面的描述很容易誤導他人,望修正。