在csapp的描述中,虛拟記憶體的形象更加具化,虛拟記憶體被組織為一個由存放在磁盤上的N個連續的位元組大小的單元組成的數組,記憶體充當了磁盤的緩存,虛拟記憶體的許多概念與SRAM緩存是相似的。虛拟頁面有以下三種狀态:
未配置設定(pte的有效位為0,且pte的位址段為空)
未緩存(pte的有效位為0,且pte的位址段指向磁盤的某一位置)
已緩存(pte的有效位為1,且pte的位址段指向記憶體的某一位置)
這是将實體位址的範圍擴大到除了記憶體之外,還包含磁盤。虛拟位址照常根據MMU進行多級頁表轉換,得到的位址可能是實體頁号(記憶體中)或者磁盤位址。虛拟記憶體系統是虛拟位址的擴充應用。

在xv6系統和JOS系統中,并沒有使用到磁盤上的虛拟記憶體,MMU得到的結果始終在記憶體上,否則就是缺頁,在記憶體上配置設定新的頁面,并無磁盤的利用。推測應該使用swap交換區來實作。
當作業系統調用malloc配置設定一個新的虛拟記憶體頁的時候,首先會在磁盤上建立空間,并更新PTE。
在磁盤和記憶體之間傳送頁面的活動稱為交換(swapping)或者頁面排程,分為換入和換出。頁面排程通常發生在有不命中發生的時候,這叫做按需頁面排程。也可以通過預測的方式提前将可能用到的頁面調入記憶體,這就有點像分支預測,但通常不被使用,可能是因為比起分支預測的懲罰,頁面排程失敗的代價比較大。由于程式的局部性,頁面排程可能不需要頻繁發生,如果工作集的大小超過了實體記憶體的大小,就不可避免地會發生頻繁的換入換出,這種狀态稱為抖動,會大大影響程式的性能。不管虛拟位址翻譯的結果在不在磁盤,最終cpu都要從記憶體讀資料,是以如果不在記憶體,有效位會是0,發生正常的缺頁,進行頁面排程,如果記憶體已滿,則要根據一些政策選擇換出頁面,這裡還涉及到像緩存裡相似的直寫和寫回的選擇。
【缺頁異常可能有三種原因】
段錯誤,通路一個不存在的頁面;
正常缺頁,則進行頁面排程,然後重新執行;
保護異常,違反了頁面的權限許可,傳回錯誤碼即可。
此外,pte上不止有有效位,還有各種标志位,控制了不同程式對頁面的通路和讀寫權限。正因為此,我們說虛拟記憶體可以更好地管理記憶體。
【關于共享記憶體】
比如圖中的PP6,作業系統對共享記憶體的控制是:不允許程序修改任何與其他程序共享的虛拟頁面,除非所有的共享者都顯式地允許它這麼做。
在Copy-On-Write中,當需要寫一段共享記憶體的時候,會将這段記憶體在另一個記憶體區域複制出副本,此時便不再是共享的記憶體,不必受到共享記憶體的限制。在其它情況下,如果要寫共享記憶體,則需要對共享者之間的程序通信,得到所有程序的允許信号後才寫入。
【由共享記憶體,可以擴充到C++多線程程式設計中的共享對象】
程序與線程的差別是,不同程序有不同的頁表基位址,不容易出現共享記憶體,而線程作為一個程序内的子單元,使用同樣的頁表基位址,記憶體都是共享的。(在xv6實驗multithreading中,提到linux對多線程的支援,待總結。)當一個對象被多個線程同時使用的時候,常常采用加鎖的方式、或者shared_ptr/weak_ptr這種智能指針的方式保證資料讀寫安全,尤其是對象析構時期的安全,此時,這段共享記憶體的安全讀寫需要另一段記憶體裡的對象的鎖成員,或者棧上的智能指針來保護,這些都是在使用者程序中顯式約定的,而不是由OS控制。
【虛拟位址到實體位址的翻譯過程】
虛拟記憶體的映射和高速緩存比較相似,那麼虛拟記憶體和高速緩存是怎麼結合,共同為CPU提供資料服務的呢?
答案是,CPU查找資料的時候,首先去cache中查找,cache查找失敗的話,也是先從記憶體load到cache中,總之是一定經過cache的,這樣的緩存原理也可以解釋為什麼近期浏覽的網頁記錄丢失的話,可以從緩存裡找到蹤迹,因為近期通路過的記憶體都會存入緩存。
除了cache高速緩存之外,為了讓cpu更快地通路記憶體,還有第二個措施,就是TLB快表。cache緩存的是實體位址對應的資料,快表緩存的是虛拟位址對應的實體位址,存放于MMU中,與處理器同在CPU晶片内。