基於《CSAPP第九章 虛擬記憶體》的思考和總結

妙妙園發表於2021-12-07

在csapp的描述中,虛擬記憶體的形象更加具化,虛擬記憶體被組織為一個由存放在磁碟上的N個連續的位元組大小的單元組成的陣列,記憶體充當了磁碟的快取,虛擬記憶體的許多概念與SRAM快取是相似的。虛擬頁面有以下三種狀態:

  1. 未分配(pte的有效位為0,且pte的地址段為空)
  2. 未快取(pte的有效位為0,且pte的地址段指向磁碟的某一位置)
  3. 已快取(pte的有效位為1,且pte的地址段指向記憶體的某一位置)

這是將實體地址的範圍擴大到除了記憶體之外,還包含磁碟。虛擬地址照常根據MMU進行多級頁錶轉換,得到的地址可能是物理頁號(記憶體中)或者磁碟地址。虛擬記憶體系統是虛擬地址的擴充套件應用。

在xv6系統和JOS系統中,並沒有使用到磁碟上的虛擬記憶體,MMU得到的結果始終在記憶體上,否則就是缺頁,在記憶體上分配新的頁面,並無磁碟的利用。推測應該使用swap交換區來實現。

當作業系統呼叫malloc分配一個新的虛擬記憶體頁的時候,首先會在磁碟上建立空間,並更新PTE。

在磁碟和記憶體之間傳送頁面的活動稱為交換(swapping)或者頁面排程,分為換入和換出。頁面排程通常發生在有不命中發生的時候,這叫做按需頁面排程。也可以通過預測的方式提前將可能用到的頁面調入記憶體,這就有點像分支預測,但通常不被使用,可能是因為比起分支預測的懲罰,頁面排程失敗的代價比較大。由於程式的區域性性,頁面排程可能不需要頻繁發生,如果工作集的大小超過了實體記憶體的大小,就不可避免地會發生頻繁的換入換出,這種狀態稱為抖動,會大大影響程式的效能。不管虛擬地址翻譯的結果在不在磁碟,最終cpu都要從記憶體讀資料,因此如果不在記憶體,有效位會是0,發生正常的缺頁,進行頁面排程,如果記憶體已滿,則要根據一些策略選擇換出頁面,這裡還涉及到像快取裡相似的直寫和寫回的選擇

【缺頁異常可能有三種原因】

  1. 段錯誤,訪問一個不存在的頁面;
  2. 正常缺頁,則進行頁面排程,然後重新執行;
  3. 保護異常,違反了頁面的許可權許可,返回錯誤碼即可。

此外,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晶片內。

相關文章