虛擬內存與物理內存
如何管理內存?
當多個程序同時運行時,如何讓多個應用程序共同使用物理內存資源?有兩種簡單的方法:
-
使某一個應用程序獨占所有的內存資源。一個程序要運行就將另一個程序的內存數據轉存到硬盤中,使要運行的程序獨占所有內存資源。
- 缺點:硬盤讀寫速度很慢(相對而言),如果應用程序頻繁切換,必然會造成大量時間開銷。
-
讓每一個應用程序獨占一部分內存資源。多個應用程序的數據,可以一直保存在內存中,避免了硬盤讀寫的時間開銷。
- 缺點:無法保證不同應用程序內存之間的隔離性,如果應用程序A錯誤讀取或修改了應用程序B的內存數據,就會造成嚴重的后果。
- 缺點:無法保證每個應用程序分到的內存地址是連續的,這會增加程序編寫的復雜度。
虛擬內存
為了使不同的應用程序高效,安全的使用內存,虛擬內存應運而生。顧名思義,虛擬內存是對物理內存的一種抽象,它介於應用程序與物理內存之間。應用程序是面向虛擬內存編寫的,而不再是面向物理內存編寫的。應用程序在運行時只能使用虛擬地址CPU負責將虛擬地址翻譯成物理地址,操作系統負責設置虛擬地址到物理地址的映射。
優點:
- 應用程序只能看到自己的虛擬地址空間,從而保證了應用程序之間內存的隔離性,使應用程序運行更安全。
- 每個應用程序的虛擬內存空間是連續的、統一的,從而降低了編程的復雜性。

地址翻譯:CPU中的內存管理單元(MMU)負責將虛擬內存翻譯成物理內存。為了加速地址翻譯過程,MMU中還加入了轉址旁路緩存(TLB),TLB可以緩存一部分虛擬地址到物理地址的映射,從而加速翻譯。
虛擬內存是硬件提供的一種功能,而不是操作系統提供的。
分段和分頁
分段和分頁是MMU將虛擬地址翻譯為物理地址的兩種機制。
分段
在分段的機制下,操作系統以“段”(一段連續的物理內存)的形式來管理、分配虛擬內存和物理內存。應用程序的虛擬地址空間由若干個不同大小的段組成,比如:代碼段、數據段。
每一段都是一個虛擬地址空間,虛擬地址由兩部分組成:段號和段內地址。MMU通過段表找到對應的物理段,再通過虛擬地址中的段內地址(偏移量)找到對應的物理地址。

缺點:造成物理出現外部碎片。虛擬地址中相鄰的段對應到物理內存中可能就不相鄰了,這樣雖然實現了物理內存的離散分配,但是可能造成物理內存中相鄰的段之間出現內存碎片(不足以映射給虛擬內存中的段)。
分頁
將應用程序的虛擬地址空間划分成連續的,等長的虛擬頁,同時物理內存也被划分為等長的,連續的虛擬頁。操作系統為每一個應用程序構造頁表(虛擬頁到物理頁的映射關系表)。分頁機制下的虛擬地址由兩部分構成:虛擬頁號和頁內偏移量。
MMU通過應用程序的頁表找到虛擬頁號對應的物理地址,再通過頁內偏移量找到對應的物理地址。

多級頁表
上面的簡單分頁機制在32位操作系統中,還能用,但是在64位操作系統中就不行了。64位操作系統,虛擬地址長64位,也就是8個字節,64位尋址范圍是0~2^64,如果一個虛擬頁大小4KB,那么就會有2^64/4KB個虛擬頁,如果用一張頁表來記錄,一個頁表項8字節,那么頁表大小就為2^64/4KB*8,這是一個無法接受的數字。為了壓縮頁表的大小,多級頁表應運而生。下面是一個4級頁表的示意圖:

在多級分頁機制下,0級頁表只有一個頁表頁,而其余每一級頁表都可以擁有多個離散的頁表頁。虛擬地址可以分為兩部分:虛擬頁號和頁內偏移。只不過虛擬頁號可以進一步分為四個部分,依次對應其在對應級數頁表中的索引。當任意一級頁表中的條目為空時,就意味着該條目對應的下一級頁表不需要存在,因此節省了大量空間(不過增加了翻譯時間,時間換空間)。
換頁和缺頁異常
換頁是一種當物理內存不足時的一種機制。物理內存緊張時,操作系統會將一些物理頁寫入到磁盤中來騰出空間,這叫換出,當物理內存不緊張時,再將換出的物理頁讀回內存,這叫換入。換頁機制能夠工作的前提是缺頁異常,物理頁被換出,但是頁表中與之對應的虛擬頁仍然處於已分配狀態,但是當應用程序訪問該虛擬頁時卻發現該虛擬頁沒有映射到物理頁,於是就會觸發缺頁異常。
利用換頁機制,操作系統可以把物理內存放不下的數據臨時存儲在磁盤上,等到需要的時候再放回到物理內存中,從而能夠為應用程序提供超過物理內存容量的虛擬內存空間,不過換頁耗時較高會使程序運行變慢,常見的頁替換策略:MIN策略/opt策略、FIFO策略、LRU策略。
