虛擬記憶體與地址空間
虛擬記憶體和地址空間是記憶體虛擬化的根本,很多時候會搞不懂這個概念和原理,本文會從三個W去講述虛擬記憶體,即Why,What和How
虛擬記憶體的產生
最早的作業系統是直接操作實體記憶體的,這個時候,每個程式都是獨享實體記憶體空間的,所以作業系統相對比較簡單;
隨著時代的發展,產生了多道程式和時分共享,就是要求作業系統能夠處理更多的計算機程式,這樣的解決方案有兩個,一是讓一個程式全部佔用記憶體執行一段時間,然後停止它,並將它狀態資訊儲存到磁碟,最後再把下一個程式裝載到記憶體中,繼續執行,這種方案太慢了,兩個程式切換太慢了;
針對上述方法改進,讓多個程序共同存在於實體記憶體中,每個程序只儲存程序一部分資訊到實體記憶體,切換的時候,依舊儲存到實體記憶體。這樣能夠有很快的效率,但是又產生程序之間實體記憶體打架的行為,所以需要給其提供保護
虛擬記憶體和地址空間是什麼
作業系統對實體記憶體進行了一個抽象叫地址空間,地址空間是是執行的程式看到的系統中的記憶體。這個抽象就是記憶體虛擬化的關鍵,就好比程序是CPU的虛擬化一樣,兩個都是對硬體的抽象,可以類比來看
一個地址空間包括程序所有的資訊,最基本的,我們談論最多的就是程式碼(指令),堆(從小到大增長),棧(從大到小增長)。當我們描述地址空間時,描述的是作業系統提供給執行程式的抽象,程式不是在實體記憶體0~16KB的記憶體中,而是在載入到任意的實體地址
如何執行
虛擬記憶體為程式提供了一個巨大的、稀疏的、私有的地址空間(一般稱為虛擬地址),這些都是對程式可見的,但是CPU執行程式的時候,是需要到實際的實體記憶體(一般稱為實體地址或實際地址)取資料,這裡需要有一個機制將虛擬地址和實體地址進行轉換,一般是通過分頁
這裡要討論的是,多個程式,都有自己的地址空間,兩個程式的地址空間的地址可能有重複,那麼如何將每個程序的地址空間對映到實體記憶體的不同部分,這個技術叫動態重定位。
動態重定位是給每個CPU配置兩個暫存器:基址暫存器和界限暫存器。程式執行時,起始地址載入到基址暫存器,程式長度載入到界限暫存器。每次指令訪問記憶體時,CPU硬體會在把地址傳送到記憶體匯流排前,自動把基址值加到程序發出的地址值上。同時,它檢查程式提供的地址是否等於或大於界限暫存器裡的值。如果訪問的地址超過了界限,會產生錯誤並中止訪問,就是頁缺失錯誤
使用基址暫存器和界限暫存器是給每個程序提供私有地址空間,同時,硬體會對這兩個暫存器進行保護,只有作業系統能夠訪問。使用這種方式的缺點是,每次訪問記憶體都要進行比較和加法運算,比較可以做得很快,但是加法由於進位傳遞時間的問題,在沒有使用特殊電路的情況下會顯得很慢。
小結
虛擬記憶體的基本思想是:每個程式擁有自己的地址空間,這個空間被分割成多個塊,每一塊稱作一頁或頁面(page)。每一頁有連續的地址範圍。這些頁被對映到實體記憶體,但並不是所有的頁都必須在記憶體中才能執行程式。當程式引用到一部分在實體記憶體中的地址空間時,由硬體立刻執行必要的對映。當程式引用到一部分不在實體記憶體中的地址空間時,由作業系統負責將缺失的部分裝入實體記憶體並重新執行失敗的指令。
從某個角度來講,虛擬記憶體是對基址暫存器和界限暫存器的一種綜合。虛擬記憶體使得整個地址空間可以用相對較小的單元對映到實體記憶體,而不是為正文段和資料段分別進行重定位