為了在多程序環境下,使得程序之間的記憶體位址不受影響,互相隔離,于是作業系統就為每個程序獨立配置設定一套虛拟位址空間,每個程式隻關心自己的虛拟位址就可以,實際上大家的虛拟位址都是一樣的,但分布到實體位址記憶體是不一樣的。作為程式,也不用關心實體位址的事情。
每個程序都有自己的虛拟空間,而實體記憶體隻有一個,是以當啟用了大量的程序,實體記憶體必然會很緊張,于是作業系統會通過記憶體交換技術,把不常使用的記憶體暫時存放到硬碟(換出),在需要的時候再裝載回實體記憶體(換入)。
那既然有了虛拟位址空間,那必然要把虛拟位址「映射」到實體位址,這個事情通常由作業系統來維護。
那麼對于虛拟位址與實體位址的映射關系,可以有分段和分頁的方式,同時兩者結合都是可以的。
記憶體分段是根據程式的邏輯角度,分成了棧段、堆段、資料段、代碼段等,這樣可以分離出不同屬性的段,同時是一塊連續的空間。但是每個段的大小都不是統一的,這就會導緻外部記憶體碎片和記憶體交換效率低的問題。
于是,就出現了記憶體分頁,把虛拟空間和實體空間分成大小固定的頁,如在 Linux 系統中,每一頁的大小為
4KB
。由于分了頁後,就不會産生細小的記憶體碎片,解決了記憶體分段的外部記憶體碎片問題。同時在記憶體交換的時候,寫入硬碟也就一個頁或幾個頁,這就大大提高了記憶體交換的效率。
再來,為了解決簡單分頁産生的頁表過大的問題,就有了多級頁表,它解決了空間上的問題,但這就會導緻 CPU 在尋址的過程中,需要有很多層表參與,加大了時間上的開銷。于是根據程式的局部性原理,在 CPU 晶片中加入了 TLB,負責緩存最近常被通路的頁表項,大大提高了位址的轉換速度。
- 第一,虛拟記憶體可以使得程序對運作記憶體超過實體記憶體大小,因為程式運作符合局部性原理,CPU 通路記憶體會有很明顯的重複通路的傾向性,對于那些沒有被經常使用到的記憶體,我們可以把它換出到實體記憶體之外,比如硬碟上的 swap 區域。
- 第二,由于每個程序都有自己的頁表,是以每個程序的虛拟記憶體空間就是互相獨立的。程序也沒有辦法通路其他程序的頁表,是以這些頁表是私有的,這就解決了多程序之間位址沖突的問題。
- 第三,頁表裡的頁表項中除了實體位址之外,還有一些标記屬性的比特,比如控制一個頁的讀寫權限,标記該頁是否存在等。在記憶體通路方面,作業系統提供了更好的安全性。