1. 程式人生 > >又能扯皮了!沒記憶體了還能看片?

又能扯皮了!沒記憶體了還能看片?

## 虛擬記憶體 儘管基址暫存器和變址暫存器用來建立地址空間的抽象,但是這有一個其他的問題需要解決:`管理軟體的膨脹(managing bloatware)`。雖然記憶體的大小增長迅速,但是軟體的大小增長的要比記憶體還要快。在 1980 年的時候,許多大學用一臺 4 MB 的 VAX 計算機執行分時作業系統,供十幾個使用者同時執行。現在微軟公司推薦的 64 位 Windows 8 系統至少需要 2 GB 記憶體,而許多多媒體的潮流則進一步推動了對記憶體的需求。 這一發展的結果是,需要執行的程式往往大到記憶體無法容納,而且必然需要系統能夠支援多個程式同時執行,即使記憶體可以滿足其中單獨一個程式的需求,但是從總體上來看記憶體仍然滿足不了日益增長的軟體的需求(感覺和xxx和xxx 的矛盾很相似)。而交換技術並不是一個很有效的方案,在一些中小應用程式尚可使用交換,如果應用程式過大,難道還要每次交換幾 GB 的記憶體?這顯然是不合適的,一個典型的 `SATA` 磁碟的峰值傳輸速度高達幾百兆/秒,這意味著需要好幾秒才能換出或者換入一個 1 GB 的程式。 >SATA(Serial ATA)硬碟,又稱串列埠硬碟,是未來 PC 機硬碟的趨勢,已基本取代了傳統的 PATA 硬碟。 那麼還有沒有一種有效的方式來應對呢?有,那就是使用 `虛擬記憶體(virtual memory)`,虛擬記憶體的基本思想是,每個程式都有自己的地址空間,這個地址空間被劃分為多個稱為`頁面(page)`的塊。每一頁都是連續的地址範圍。這些頁被對映到實體記憶體,但並不是所有的頁都必須在記憶體中才能執行程式。當程式引用到一部分在實體記憶體中的地址空間時,硬體會立刻執行必要的對映。當程式引用到一部分不在實體記憶體中的地址空間時,由作業系統負責將缺失的部分裝入實體記憶體並重新執行失敗的指令。 在某種意義上來說,虛擬地址是對基址暫存器和變址暫存器的一種概述。8088 有分離的基址暫存器(但不是變址暫存器)用於放入 text 和 data 。 使用虛擬記憶體,可以將整個地址空間以很小的單位對映到實體記憶體中,而不是僅僅針對 text 和 data 區進行重定位。下面我們會探討虛擬記憶體是如何實現的。 虛擬記憶體很適合在多道程式設計系統中使用,許多程式的片段同時儲存在記憶體中,當一個程式等待它的一部分讀入記憶體時,可以把 CPU 交給另一個程序使用。 ### 分頁 大部分使用虛擬記憶體的系統中都會使用一種 `分頁(paging)` 技術。在任何一臺計算機上,程式會引用使用一組記憶體地址。當程式執行 ```assembly MOV REG,1000 ``` 這條指令時,它會把記憶體地址為 1000 的記憶體單元的內容複製到 REG 中(或者相反,這取決於計算機)。地址可以通過索引、基址暫存器、段暫存器或其他方式產生。 這些程式生成的地址被稱為 `虛擬地址(virtual addresses)` 並形成`虛擬地址空間(virtual address space)`,在沒有虛擬記憶體的計算機上,系統直接將虛擬地址送到記憶體中線上,讀寫操作都使用同樣地址的實體記憶體。**在使用虛擬記憶體時,虛擬地址不會直接傳送到記憶體總線上**。相反,會使用 `MMU(Memory Management Unit)` 記憶體管理單元把**虛擬地址對映為實體記憶體地址**,像下圖這樣 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141225007-642006335.png) 下面這幅圖展示了這種對映是如何工作的 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141233462-667037066.png) 頁表給出虛擬地址與實體記憶體地址之間的對映關係。每一頁起始於 4096 的倍數位置,結束於 4095 的位置,所以 4K 到 8K 實際為 4096 - 8191 ,8K - 12K 就是 8192 - 12287 在這個例子中,我們可能有一個 16 位地址的計算機,地址從 0 - 64 K - 1,這些是`虛擬地址`。然而只有 32 KB 的實體地址。所以雖然可以編寫 64 KB 的程式,但是程式無法全部調入記憶體執行,在磁碟上必須有一個最多 64 KB 的程式核心映像的完整副本,以保證程式片段在需要時被調入記憶體。 #### 存在對映的頁如何對映 虛擬地址空間由固定大小的單元組成,這種固定大小的單元稱為 `頁(pages)`。而相對的,實體記憶體中也有固定大小的物理單元,稱為 `頁框(page frames)`。頁和頁框的大小一樣。在上面這個例子中,頁的大小為 4KB ,但是實際的使用過程中頁的大小範圍可能是 512 位元組 - 1G 位元組的大小。對應於 64 KB 的虛擬地址空間和 32 KB 的實體記憶體,可得到 16 個虛擬頁面和 8 個頁框。RAM 和磁碟之間的交換總是以整個頁為單元進行交換的。 程式試圖訪問地址時,例如執行下面這條指令 ```assembly MOV REG, 0 ``` 會將虛擬地址 0 送到 MMU。MMU 看到虛擬地址落在頁面 0 (0 - 4095),根據其對映結果,這一頁面對應的頁框 2 (8192 - 12287),因此 MMU 把地址變換為 8192 ,並把地址 8192 送到總線上。記憶體對 MMU 一無所知,它只看到一個對 8192 地址的讀寫請求並執行它。MMU 從而有效的把所有虛擬地址 0 - 4095 對映到了 8192 - 12287 的實體地址。同樣的,指令 ```assembly MOV REG, 8192 ``` 也被有效的轉換為 ```assembly MOV REG, 24576 ``` 虛擬地址 8192(在虛擬頁 2 中)被對映到實體地址 24576(在物理頁框 6 中)上。 通過恰當的設定 MMU,可以把 16 個虛擬頁面對映到 8 個頁框中的任何一個。但是這並沒有解決虛擬地址空間比實體記憶體大的問題。 上圖中有 8 個物理頁框,於是只有 8 個虛擬頁被對映到了實體記憶體中,在上圖中用 `X` 號表示的其他頁面沒有被對映。在實際的硬體中,會使用一個 `在/不在(Present/absent bit)`位記錄頁面在記憶體中的實際存在情況。 #### 未對映的頁如何對映 當程式訪問一個未對映的頁面,如執行指令 ```assembly MOV REG, 32780 ``` 將會發生什麼情況呢?虛擬頁面 8 (從 32768 開始)的第 12 個位元組所對應的實體地址是什麼?MMU 注意到該頁面沒有被對映(在圖中用 X 號表示),於是 CPU 會`陷入(trap)`到作業系統中。這個陷入稱為 `缺頁中斷(page fault)` 或者是 `缺頁錯誤`。作業系統會選擇一個很少使用的頁並把它的內容寫入磁碟(如果它不在磁碟上)。隨後把需要訪問的頁面讀到剛才回收的頁框中,修改對映關係,然後重新啟動引起陷入的指令。有點不太好理解,舉個例子來看一下。 例如,如果作業系統決定放棄頁框 1,那麼它將把虛擬機器頁面 8 裝入實體地址 4096,並對 MMU 對映做兩處修改。首先,它要將虛擬頁中的 1 表項標記為未對映,使以後任何對虛擬地址 4096 - 8191 的訪問都將導致陷入。隨後把虛擬頁面 8 的表項的叉號改為 1,因此在引起陷阱的指令重新啟動時,它將把虛擬地址 32780 對映為實體地址(4096 + 12)。 下面檢視一下 MMU 的內部構造以便了解它們是如何工作的,以及瞭解為什麼我們選用的頁大小都是 2 的整數次冪。下圖我們可以看到一個虛擬地址的例子 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141248081-359450732.png) 虛擬地址 8196 (二進位制 0010000000000100)用上面的頁表對映圖所示的 MMU 對映機制進行對映,輸入的 16 位虛擬地址被分為 4 位的頁號和 12 位的偏移量。4 位的頁號可以表示 16 個頁面,12 位的偏移可以為一頁內的全部 4096 個位元組。 可用頁號作為`頁表(page table)` 的索引,以得出對應於該虛擬頁面的頁框號。如果`在/不在`位則是 0 ,則引起一個作業系統陷入。如果該位是 1,則將在頁表中查到的頁框號複製到輸出暫存器的高 3 位中,再加上輸入虛擬地址中的低 12 位偏移量。如此就構成了 15 位的實體地址。輸出暫存器的內容隨即被作為實體地址送到匯流排。 ### 頁表 在上面這個簡單的例子中,虛擬地址到實體地址的對映可以總結如下:虛擬地址被分為`虛擬頁號(高位部分)`和`偏移量(低位部分)`。例如,對於 16 位地址和 4 KB 的頁面大小,高 4 位可以指定 16 個虛擬頁面中的一頁,而低 12 位接著確定了所選頁面中的偏移量(0-4095)。 虛擬頁號可作為頁表的索引用來找到虛擬頁中的內容。由頁表項可以找到頁框號(如果有的話)。然後把頁框號拼接到偏移量的高位端,以替換掉虛擬頁號,形成實體地址。 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141259283-1125376414.png) 因此,頁表的目的是把虛擬頁對映到頁框中。從數學上說,頁表是一個函式,它的引數是虛擬頁號,結果是物理頁框號。 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141307749-1345838673.png) 通過這個函式可以把虛擬地址中的虛擬頁轉換為頁框,從而形成實體地址。 #### 頁表項的結構 下面我們探討一下頁表項的具體結構,上面你知道了頁表項的大致構成,是由頁框號和在/不在位構成的,現在我們來具體探討一下頁表項的構成 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141316491-1987265911.png) 頁表項的結構是與機器相關的,但是不同機器上的頁表項大致相同。上面是一個頁表項的構成,不同計算機的頁表項可能不同,但是一般來說都是 32 位的。頁表項中最重要的欄位就是`頁框號(Page frame number)`。畢竟,頁表到頁框最重要的一步操作就是要把此值對映過去。下一個比較重要的就是`在/不在`位,如果此位上的值是 1,那麼頁表項是有效的並且能夠被`使用`。如果此值是 0 的話,則表示該頁表項對應的虛擬頁面`不在`記憶體中,訪問該頁面會引起一個`缺頁異常(page fault)`。 `保護位(Protection)` 告訴我們哪一種訪問是允許的,啥意思呢?最簡單的表示形式是這個域只有一位,**0 表示可讀可寫,1 表示的是隻讀**。 `修改位(Modified)` 和 `訪問位(Referenced)` 會跟蹤頁面的使用情況。當一個頁面被寫入時,硬體會自動的設定修改位。修改位在頁面重新分配頁框時很有用。如果一個頁面已經被修改過(即它是 `髒` 的),則必須把它寫回磁碟。如果一個頁面沒有被修改過(即它是 `乾淨`的),那麼重新分配時這個頁框會被直接丟棄,因為磁碟上的副本仍然是有效的。這個位有時也叫做 `髒位(dirty bit)`,因為它反映了頁面的狀態。 `訪問位(Referenced)` 在頁面被訪問時被設定,不管是讀還是寫。這個值能夠幫助作業系統在發生缺頁中斷時選擇要淘汰的頁。不再使用的頁要比正在使用的頁更適合被淘汰。這個位在後面要討論的`頁面置換`演算法中作用很大。 最後一位用於禁止該頁面被快取記憶體,這個功能對於對映到裝置暫存器還是記憶體中起到了關鍵作用。通過這一位可以禁用快取記憶體。具有獨立的 I/O 空間而不是用記憶體對映 I/O 的機器來說,並不需要這一位。 在深入討論下面問題之前,需要強調一下:虛擬記憶體本質上是用來創造一個地址空間的抽象,可以把它理解成為程序是對 CPU 的抽象,虛擬記憶體的實現,本質是將虛擬地址空間分解成頁,並將每一項對映到實體記憶體的某個頁框。因為我們的重點是如何管理這個虛擬記憶體的抽象。 ### 加速分頁過程 到現在我們已經`虛擬記憶體(virtual memory)` 和 `分頁(paging)` 的基礎,現在我們可以把目光放在具體的實現上面了。在任何帶有分頁的系統中,都會需要面臨下面這兩個主要問題: * 虛擬地址到實體地址的對映速度必須要快 * 如果虛擬地址空間足夠大,那麼頁表也會足夠大 第一個問題是**由於每次訪問記憶體都需要進行虛擬地址到實體地址的對映**,所有的指令最終都來自於記憶體,並且很多指令也會訪問記憶體中的運算元。 >運算元:運算元是計算機指令中的一個組成部分,它規定了指令中進行數字運算的量 。運算元指出指令執行的操作所需要資料的來源。運算元是彙編指令的一個欄位。比如,MOV、ADD 等。 因此,每條指令可能會多次訪問頁表,如果執行一條指令需要 1 ns,那麼頁表查詢需要在 0.2 ns 之內完成,以避免對映成為一個主要效能瓶頸。 第二個問題是所有的現代作業系統都會使用至少 32 位的虛擬地址,並且 64 位正在變得越來越普遍。假設頁大小為 4 KB,32 位的地址空間將近有 100 萬頁,而 64 位地址空間簡直多到無法想象。 對大而且快速的頁對映的需要成為構建計算機的一個非常重要的約束。就像上面頁表中的圖一樣,**每一個表項對應一個虛擬頁面,虛擬頁號作為索引**。在啟動一個程序時,作業系統會把儲存在記憶體中程序頁表讀副本放入暫存器中。 >最後一句話是不是不好理解?還記得頁表是什麼嗎?它是虛擬地址到記憶體地址的對映頁表。頁表是虛擬地址轉換的關鍵組成部分,它是訪問記憶體中資料所必需的。在程序啟動時,執行很多次虛擬地址到實體地址的轉換,會把實體地址的副本從記憶體中讀入到暫存器中,再執行這一轉換過程。 所以,在程序的執行過程中,不必再為頁表而訪問記憶體。使用這種方法的優勢是`簡單而且對映過程中不需要訪問記憶體`。缺點是 `頁表太大時,代價高昂`,而且每次上下文切換的時候都必須`裝載整個頁表`,這樣會造成效能的降低。鑑於此,我們討論一下加速分頁機制和處理大的虛擬地址空間的實現方案 #### 轉換檢測緩衝區 我們首先先來一起探討一下加速分頁的問題。大部分優化方案都是從記憶體中的頁表開始的。這種設計對效率有著巨大的影響。考慮一下,例如,假設一條 1 位元組的指令要把一個暫存器中的資料複製到另一個暫存器。在不分頁的情況下,這條指令只訪問一次記憶體,即從記憶體取出指令。有了分頁機制後,會因為要訪問頁表而需要更多的記憶體訪問。由於執行速度通常被 CPU 從記憶體中取指令和資料的速度所限制,這樣的話,兩次訪問才能實現一次的訪問效果,所以記憶體訪問的效能會下降一半。在這種情況下,根本不會採用分頁機制。 >什麼是 1 位元組的指令?我們以 8085 微處理器為例來說明一下,在 8085 微處理中,一共有 3 種位元組指令,它們分別是 `1-byte(1 位元組)`、`2-byte(2 位元組)`、`3-byte(3 位元組)`,我們分別來說一下 > >1-byte:1 位元組的運算元和操作碼共同以 1 位元組表示;運算元是內部暫存器,並被編碼到指令中;指令需要一個儲存位置來將單個暫存器儲存在儲存位置中。沒有運算元的指令也是 1-byte 指令。 > >例如:MOV B,C 、LDAX B、NOP、HLT(這塊不明白的讀者可以自行查閱) > >2-byte: 2 位元組包括:第一個位元組指定的操作碼;第二個位元組指定運算元;指令需要兩個儲存器位置才能儲存在儲存器中。 > >例如 MVI B, 26 H、IN 56 H > >3-byte: 在 3 位元組指令中,第一個位元組指定操作碼;後面兩個位元組指定 16 位的地址;第二個位元組儲存`低位`地址;第三個位元組儲存 `高位`地址。指令需要三個儲存器位置才能將單個位元組儲存在儲存器中。 > >例如 LDA 2050 H、JMP 2085 H 大多數程式總是對少量頁面進行多次訪問,而不是對大量頁面進行少量訪問。因此,只有很少的頁面能夠被再次訪問,而其他的頁表項很少被訪問。 >頁表項一般也被稱為 `Page Table Entry(PTE)`。 基於這種設想,提出了一種方案,即從硬體方面來解決這個問題,為計算機設定一個小型的硬體裝置,能夠將虛擬地址直接對映到實體地址,而不必再訪問頁表。這種裝置被稱為`轉換檢測緩衝區(Translation Lookaside Buffer, TLB)`,有時又被稱為 `相聯儲存器(associate memory)` 。 | 有效位 | 虛擬頁面號 | 修改位 | 保護位 | 頁框號 | | :----: | :--------: | :----: | :----: | :----: | | 1 | 140 | 1 | RW | 31 | | 1 | 20 | 0 | R X | 38 | | 1 | 130 | 1 | RW | 29 | | 1 | 129 | 1 | RW | 62 | | 1 | 19 | 0 | R X | 50 | | 1 | 21 | 0 | R X | 45 | | 1 | 860 | 1 | RW | 14 | | 1 | 861 | 1 | RW | 75 | ​ TLB 加速分頁 TLB 通常位於 MMU 中,包含少量的表項,每個表項都記錄了頁面的相關資訊,除了虛擬頁號外,其他表項都和頁表是一一對應的 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141333412-327892809.png) 是不是你到現在還是有點不理解什麼是 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 中時,所有的值都來自於記憶體。 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141345998-350761161.png) #### 軟體 TLB 管理 直到現在,我們假設每臺電腦都有可以被硬體識別的頁表,外加一個 TLB。在這個設計中,TLB 管理和處理 TLB 錯誤完全由硬體來完成。僅僅當頁面不在記憶體中時,才會發生作業系統的`陷入(trap)`。 在以前,我們上面的假設通常是正確的。但是,許多現代的 `RISC` 機器,包括 SPARC、MIPS 和 HP PA,幾乎所有的頁面管理都是在軟體中完成的。 >精簡指令集計算機或 RISC 是一種計算機指令集,它使計算機的微處理器的每條指令(CPI)週期比複雜指令集計算機(CISC)少 在這些計算機上,TLB 條目由作業系統顯示載入。當發生 TLB 訪問丟失時,**不再是由 MMU 到頁表中查詢並取出需要的頁表項,而是生成一個 TLB 失效並將問題交給作業系統解決**。作業系統必須找到該頁,把它從 TLB 中移除(移除頁表中的一項),然後把新找到的頁放在 TLB 中,最後再執行先前出錯的指令。然而,所有這些操作都必須通過少量指令完成,因為 TLB 丟失的發生率要比出錯率高很多。 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141357890-145222548.png) 無論是用硬體還是用軟體來處理 TLB 失效,常見的方式都是找到頁表並執行索引操作以定位到將要訪問的頁面,在軟體中進行搜尋的問題是儲存頁表的頁可能不在 TLB 中,這將在處理過程中導致其他 TLB 錯誤。改善方法是可以在記憶體中的固定位置維護一個大的 TLB 表項的快取記憶體來減少 TLB 失效。通過首先檢查軟體的快取記憶體,`作業系統` 能夠有效的減少 TLB 失效問題。 TLB 軟體管理會有兩種 TLB 失效問題,當一個頁訪問在記憶體中而不在 TLB 中時,將產生 `軟失效(soft miss)`,那麼此時要做的就是把頁表更新到 TLB 中(我們上面探討的過程),而不會產生磁碟 I/O,處理僅僅需要一些機器指令在幾納秒的時間內完成。然而,當頁本身不在記憶體中時,將會產生`硬失效(hard miss)`,那麼此時就需要從磁碟中進行頁表提取,硬失效的處理時間通常是軟失效的百萬倍。在頁表結構中查詢對映的過程稱為 `頁表遍歷(page table walk)`。 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141410618-825188772.png) 上面的這兩種情況都是理想情況下出現的現象,但是在實際應用過程中情況會更加複雜,未命中的情況可能既不是硬失效又不是軟失效。一些未命中可能更`軟`或更`硬`(偷笑)。比如,如果頁表遍歷的過程中沒有找到所需要的頁,那麼此時會出現三種情況: * 所需的頁面就在記憶體中,但是卻沒有記錄在程序的頁表中,這種情況可能是由其他程序從磁碟掉入記憶體,這種情況只需要把頁正確對映就可以了,而不需要在從硬碟調入,這是一種軟失效,稱為 `次要缺頁錯誤(minor page fault)`。 * 基於上述情況,如果需要從硬碟直接調入頁面,這就是`嚴重缺頁錯誤(major page falut)`。 * 還有一種情況是,程式可能訪問了一個非法地址,根本無需向 TLB 中增加對映。此時,作業系統會報告一個 `段錯誤(segmentation fault)` 來終止程式。只有第三種缺頁屬於程式錯誤,其他缺頁情況都會被硬體或作業系統以降低程式效能為代價來修復 ### 針對大記憶體的頁表 還記得我們討論的是什麼問題嗎?(捂臉),可能討論的太多你有所不知道了,我再提醒你一下,上面`加速分頁`過程討論的是**虛擬地址到實體地址的對映速度必須要快**的問題,還有一個問題是 **如果虛擬地址空間足夠大,那麼頁表也會足夠大**的問題,如何處理巨大的虛擬地址空間,下面展開我們的討論。 #### 多級頁表 第一種方案是使用`多級頁表(multi)`,下面是一個例子 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141419045-1544103090.png) 32 位的虛擬地址被劃分為 10 位的 PT1 域,10 位的 PT2 域,還有 12 位的 Offset 域。因為偏移量是 12 位,所以頁面大小是 4KB,公有 2^20 次方個頁面。 **引入多級頁表的原因是避免把全部頁表一直儲存在記憶體中。不需要的頁表就不應該保留**。 多級頁表是一種分頁方案,它由兩個或多個層次的分頁表組成,也稱為分層分頁。級別1(level 1)頁面表的條目是指向級別 2(level 2) 頁面表的指標,級別2頁面表的條目是指向級別 3(level 3) 頁面表的指標,依此類推。最後一級頁表儲存的是實際的資訊。 下面是一個二級頁表的工作過程 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141434536-1904201520.png) 在最左邊是頂級頁表,它有 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 失效時,需要用軟體搜尋整個倒排頁表。一個可行的方式是建立一個散列表,用虛擬地址來雜湊。當前所有記憶體中的具有相同雜湊值的虛擬頁面被連結在一起。如下圖所示 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141445120-499527482.png) 如果散列表中的槽數與機器中物理頁面數一樣多,那麼散列表的衝突鏈的長度將會是 1 個表項的長度,這將會大大提高對映速度。一旦頁框被找到,新的(虛擬頁號,物理頁框號)就會被裝在到 TLB 中。 ## 刊誤 ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141505736-1324762815.png) P115 頁,兩條線位置畫反,根據下面的描述很容易誤導他人,望修正。 文章參考: https://en.wikipedia.org/wiki/Page_replacement_algorithm http://faculty.salina.k-state.edu/tim/ossg/Memory/virt_mem/page_replace.html https://www.geeksforgeeks.org/page-replacement-algorithms-in-operating-systems/ https://www.geeksforgeeks.org/multilevel-paging-in-operating-system/ https://en.wikipedia.org/wiki/Translation_lookaside_buffer https://electricalvoice.com/instruction-word-size-8085-microprocessor/ https://en.wikipedia.org/wiki/Page_table https://www.javatpoint.com/os-page-table https://baike.baidu.com/item/記憶體/103614?fr=aladdin https://baike.baidu.com/item/資料段/5136260?fromtitle=data%20segment&fromid=18082638&fr=aladdin https://blog.csdn.net/One_L_Star/article/details/81901186 《現代作業系統》第四版 《Modern Operation System》fourth https://baike.baidu.com/item/SATA硬碟/3947233?fr=aladdin https://baike.baidu.com/item/虛擬地址/1329947?fr=aladdin ![](https://img2020.cnblogs.com/blog/1515111/202003/1515111-20200306141532940-1455247096.png)