虛擬記憶體系統——瞭解記憶體的工作原理
1、地址空間
在現代作業系統中,當CPU需要訪問主存的時候,會先生成一個虛擬地址,這個虛擬地址經過地址翻譯單元,將其翻譯成實體地址,然後使用這個實體地址來訪問主存。
一個帶虛擬記憶體的系統中,CPU可以生成n位的虛擬地址空間。現代作業系統一般支援32位或64位虛擬地址空間,也就是包含最多2 ^ 32或 2 ^ 64個地址。
除了虛擬地址空間,還有一個概念是實體地址空間,對應了實體記憶體的M個位元組。
主存中的每個位元組都有一個位於虛擬地址空間的虛擬地址和一個位於實體地址空間的實體地址。
2、虛擬記憶體的概念
虛擬記憶體是一個存放在磁碟上的大型陣列。陣列的每個位元組都有一個唯一的虛擬地址,對映為陣列的索引。主存是磁碟的快取記憶體。磁碟上的資料被分割成塊,作為磁碟和主存之間傳輸資料的單元。虛擬記憶體分割的塊被稱為虛擬頁。
虛擬頁的狀態共分三種:
1)虛擬記憶體系統還未分配的頁,不佔用磁碟空間
2)已分配的頁,並且已經快取到記憶體中
3)已分配的頁,但還沒快取在記憶體中
3、地址翻譯
CPU通常只生成一個虛擬地址,如果要把這個虛擬地址翻譯成實體地址,就需要用到MMU(記憶體管理單元)中的地址翻譯硬體和一個存放在記憶體中、稱為頁表的資料結構。
翻譯過程:
CPU生成一個虛擬地址,0 ~ p-1位為頁偏移,頁的大小即2 ^ (p-1),p ~ n-1位為虛擬頁號,與頁表索引相對應。
在頁表中找到對應的行(頁表條目)後,如果有效位為1,表示頁面的記憶體中,可以使用頁表條目的物理頁號,物理頁的偏移量與虛擬頁的偏移量相對應。物理頁號和物理頁偏移量拼接成實體地址。
如果有效位為0,則表示頁面不在記憶體中,也就是缺頁了。此時會呼叫核心的缺頁異常程式,該程式需要先淘汰記憶體中的一個頁,如果這個頁被修改過,屬於髒頁,那麼核心會將其寫回磁碟,然後再淘汰它。接下來,核心從磁碟複製所需的頁面到記憶體中,更新頁表中的對應條目,隨後返回。
當異常處理程式返回時,會重新啟動導致缺頁的指令,然後將原先那個導致缺頁的虛擬地址重新進行翻譯。此時,將會按照有效位為1進行後續處理。
TLB:很多系統,在MMU中加入了一個快取頁表條目的翻譯後備緩衝器(TLB),這樣可以快速地獲取頁表條目,整個地址翻譯步驟都是在硬體上完成,非常快。
4、虛擬記憶體的記憶體管理
1)簡化連結。作業系統為每個程式提供一個獨立的頁表,因此,每個程式都有一個獨立的虛擬地址空間。獨立的地址空間允許每個程式的記憶體映像都使用相同的基本格式,不用管程式碼和資料實際存放在哪個物理位置。這樣的操作極大地簡化連結器的設計和實現,允許連結器生成完全連結的可執行檔案,這些可執行檔案獨立於最終的物理位置。
比如,linux系統上每個程式的記憶體格式基本類似,64位地址空間中,程式碼段都被放置在0x400000開始的位置,然後是資料段,高地址是棧空間,向下生長。
2)簡化載入。要把可執行目標檔案的程式碼和資料載入到一個新建立的程式中時,載入器無需從磁碟複製任何資料到記憶體中。實際上,linux載入器只為程式碼和資料段分配虛擬頁,將頁表條目的有效位設定為0(即未快取到記憶體),再指向磁碟目標檔案中對應的.text節(儲存程式碼)和.data節(儲存資料)。虛擬作業系統在CPU取指令時會自動調入內碼表,在某一指令要引用某個記憶體位置時自動調入資料頁。
下圖是一個可重定位的目標檔案的基本格式。其中,.text包含編譯完成的機器程式碼,.rodata包含只讀資料,.data包含已初始化的全域性和靜態C變數(區域性變數執行時儲存在棧中),.bss包含未初始化的全域性和靜態C變數以及所有僅被初始化為0的全域性或靜態變數(在目標檔案中未初始化變數不佔用任何磁碟空間,執行時刻,這些變數的初始值都為0),.symtab包含一張符號表(存放了程式中定義和引用的函式和全域性變數的資訊),.rel.text包含一個.text節中位置的列表(在連結時,如果本模組呼叫了外部函式,需要修改這些位置),.rel.data包含了本模組引用或定義的所有全域性變數的重定位資訊(如果已初始化的全域性變數,它的初始化值是一個全域性變數地址或者外部定義函式的地址,都需要修改)。
3)簡化共享。雖然程式之間大部分地址空間都是私有的,但還是有一些程式碼和資料是可以共享的,比如作業系統的核心程式碼,標準庫中的函式等。作業系統讓不同程式的虛擬地址都對映到這些需要被共享的相同的物理頁面上,這樣可以使得這部分程式碼和資料在記憶體中只保留一份。
4)簡化動態記憶體分配。當程式需要在堆上動態分配記憶體時,作業系統只需要分配所需的k個連續的虛擬記憶體頁面,並將其對映到記憶體中任意位置的k個任意的物理頁面,這k個頁面可以分散在實體記憶體中。
5、小結
虛擬記憶體提供了三個重要能力:
1)將主存作為磁碟的快取,主存中只儲存程式活動區域。根據需要,在磁碟和主存之間來回傳送資料。這種方式高效地使用了主存。
2)為每個程式提供了一致性的地址空間,簡化了記憶體管理。
3)保護每個程式的地址空間私有化,不被其他程式破壞。
參考資料:《深入理解計算機系統》
相關文章
- 計算機作業系統——虛擬記憶體與實體記憶體計算機作業系統記憶體
- 【Java基礎】實體記憶體&虛擬記憶體Java記憶體
- 虛擬記憶體有什麼用 虛擬記憶體不足怎麼解決記憶體
- win10 8g記憶體還需要虛擬記憶體嗎 win10系統8g記憶體怎麼分配虛擬記憶體Win10記憶體
- Linux 虛擬記憶體Linux記憶體
- 聊聊虛擬記憶體記憶體
- win10怎麼加虛擬記憶體_win10系統增加虛擬記憶體教程Win10記憶體
- win10怎麼清除虛擬記憶體 win10系統虛擬記憶體清理的辦法Win10記憶體
- 記憶體管理兩部曲之虛擬記憶體管理記憶體
- 5.虛擬記憶體記憶體
- win11系統設定虛擬記憶體記憶體
- windows10系統如何增加虛擬記憶體Windows記憶體
- win10系統4g的記憶體設定多大的虛擬記憶體合適Win10記憶體
- win10 8g記憶體虛擬記憶體設定多少合適_win10 8g記憶體怎麼分配虛擬記憶體Win10記憶體
- 虛擬記憶體(待補充)記憶體
- Linux記憶體不夠了?看看如何開啟虛擬記憶體增加記憶體使用量Linux記憶體
- 關於虛擬機器記憶體和JVM記憶體設定的思考虛擬機記憶體JVM
- win10系統16g記憶體推薦虛擬記憶體設定多少合適Win10記憶體
- win10怎樣刪虛擬記憶體_Win10虛擬記憶體如何關閉Win10記憶體
- 虛擬記憶體對 OI 的影響記憶體
- win10怎麼刪除虛擬記憶體 刪除win10虛擬記憶體的方法Win10記憶體
- JAVA 虛擬機器可用記憶體Java虛擬機記憶體
- Linux 虛擬記憶體引數配置Linux記憶體
- Ubuntu 新增虛擬記憶體檔案Ubuntu記憶體
- 詳細理解Linux虛擬記憶體Linux記憶體
- win10虛擬記憶體怎麼設定 win10虛擬記憶體設定步驟詳解Win10記憶體
- win10怎麼更改虛擬記憶體_win10更改虛擬記憶體大小方法Win10記憶體
- win10怎麼調整虛擬記憶體_win10怎麼調虛擬記憶體Win10記憶體
- win10虛擬記憶體如何優化_win10怎麼優化虛擬記憶體Win10記憶體優化
- win10 虛擬記憶體怎麼設定好 win10 虛擬記憶體設定方法Win10記憶體
- 怎麼設定虛擬記憶體win10 win10虛擬記憶體如何設定記憶體Win10
- win10虛擬記憶體怎麼設定 win10虛擬記憶體設定方法Win10記憶體
- 詳細瞭解 InnoDB 記憶體結構及其原理記憶體
- Java虛擬機器記憶體區域詳解Java虛擬機記憶體
- 如何檢視linux系統中空閒記憶體/實體記憶體使用/剩餘記憶體Linux記憶體
- Win10系統C盤虛擬記憶體怎麼設定?Win10專業版系統C盤虛擬記憶體設定方法Win10記憶體
- win10虛擬記憶體怎麼設定 筆記本win10虛擬記憶體怎麼看Win10記憶體筆記
- 【譯】JavaScript的工作原理:記憶體管理和4種常見的記憶體洩漏JavaScript記憶體