計算機的存儲系統(tǒng)
為什么要有虛擬內存
在早期的計算機中筑凫,是沒有虛擬內存的概念的。我們要運行一個程序并村,會把程序全部裝入內存巍实,然后運行。
當運行多個程序時哩牍,經(jīng)常會出現(xiàn)一下問題:
-
進程地址空間不隔離棚潦,沒有權限保護
由于程序都是直接訪問物理內存,所以一個進程可以修改其他的內存數(shù)據(jù)膝昆,甚至修改內核地址空間中的數(shù)據(jù)丸边。 -
內存使用效率低
當內存空間不足時,要將其他程序暫時拷貝到硬盤荚孵,然后將新的程序裝入裝出妹窖,內存使用效率會十分低下。 -
程序運行的地址不確定
因為內存地址是隨機分配的收叶,所以程序運行的地址也是不確定的嘱吗。
進程的虛擬地址空間
- 每個進程都有自己獨立的4G內存空間
- 虛擬內存空間通過MMU來和真實的物理內存產生聯(lián)系
計算機明明沒有那么多內存(n個進程的話就需要n*4G內存)
虛擬內存和物理內存如何建立起來聯(lián)系的呢
Linux的虛擬內存技術
Linux把虛存空間分成若干個大小相等的存儲分區(qū),Linux把這樣的分區(qū)叫做頁滔驾。為了換入谒麦、換出的方便,物理內存也按大小分成若干個塊哆致。由于物理內存中的塊空間是用來容納虛擬頁的容器绕德,所以物理內存中的塊叫做頁框。
頁與頁框是Linux實現(xiàn)虛擬內存技術的基礎摊阀。
分頁和分表
我們知道系統(tǒng)里面的單位都是Byte字節(jié)耻蛇。如果將每一個虛擬內存的Byte都對應到物理內存的地址,每個條目最少需要8字節(jié)胞此,(32位虛擬內存->32位物理地址)臣咖,在4G內存的情況下,就需要32GB的空間來存放對照表漱牵,那么這張表就大得真正的物理地址也放不下夺蛇,于是操作系統(tǒng)引入了==頁(page)==的概念。
在系統(tǒng)啟動時酣胀,操作系統(tǒng)將整個物理內存以4K為單位刁赦,劃分為各個頁娶聘。之后進行內存分配時,都以頁為單位甚脉,那么虛擬內存頁對應物理內存頁的映射表就大大減小了丸升,4G內存,只需要8M的映射表即可牺氨,一些進程沒有使用到的虛擬內存狡耻,也并不需要保存映射關系,而且Linux還為大內存設計了多級頁表猴凹,可以進一步減少內存消耗夷狰。操作系統(tǒng)虛擬內存到物理內存的映射表,就被稱為頁表精堕。
虛擬內存的頁孵淘,物理內存的頁框及頁表
物理內存和虛擬內存被分為頁框和頁之后,其存儲單元原來的地址都被自然地分成了兩段歹篓,并且這兩段各自代表著不同的意義:高段位分別是頁框和頁碼瘫证,它們是識別頁框和頁的編碼;低段位分別叫做頁框偏移量和頁內偏移量庄撮,它們是存儲單元在頁框和頁內的地址編碼背捌。下圖就是兩段虛擬內存和物理內存分頁之后的情況:
為了使系統(tǒng)可以正確的訪問虛存頁在對應頁框中的映像,在把一個頁映射到某個頁框上的同時洞斯,就必須把頁碼和存放該頁映像的頁框碼填入一個叫做頁表的表項中毡庆。這個頁表就是之前提到的映射記錄表。一個頁的示意圖如下所示:
頁模式下烙如,虛擬地址么抗、物理地址轉換關系的示意圖如下所示:
也就是說:處理器遇到的地址都是虛擬地址。虛擬地址和物理地址都分成頁碼(頁框碼)和偏移量兩部分亚铁。在由虛擬地址轉換成物理地址的過程中翔曲,偏移量不變髓涯。而頁碼和頁框碼之間的映射就在一個映射記錄表(頁表)中祠斧。
頁表共享
在多程序系統(tǒng)中砂轻,常常有多個程序需要共享同一段代碼或數(shù)據(jù)的情況。在分頁管理的存儲器中然爆,這個事情很好辦:讓多個程序共享同一個頁面即可站粟。
具體的方法是:使這些相關程序的虛擬空間的頁面在頁表中指向內存中的同一個頁框。這樣曾雕,當程序運行并訪問這些相關頁面時奴烙,就都是對同一個頁框中的頁面進行訪問,而該頁框中的頁就被這些程序所共享。下圖是3個程序共享一個頁面的例子:
虛擬內存帶來的好處
進程內存管理
它有助于進程進行內存管理缸沃,主要體現(xiàn)在:
- 內存完整性:由于虛擬內存對進程的"欺騙"恰起,每個進程都認為自己獲取的內存是一塊連續(xù)的地址修械。我們在編寫應用程序時趾牧,就不用考慮大塊地址的分配,總是認為系統(tǒng)有足夠的大塊內存肯污。
- 安全:由于進程訪問內存時翘单,都要通過頁表來尋址,操作系統(tǒng)在頁表的各個項目上添加各種訪問權限標識位蹦渣,就可以實現(xiàn)內存的權限控制哄芜。
數(shù)據(jù)共享
通過虛擬內存更容易實現(xiàn)內存和數(shù)據(jù)的共享。
在進程加載系統(tǒng)庫時柬唯,總是先分配一塊內存认臊,將磁盤中的庫文件加載到這塊內存中,在直接使用物理內存時锄奢,由于物理內存地址唯一失晴,即使系統(tǒng)發(fā)現(xiàn)同一個庫在系統(tǒng)內加載了兩次,但每個進程指定的加載內存不一樣拘央,系統(tǒng)也無能為力涂屁。
而在使用虛擬內存時,系統(tǒng)只需要將進程的虛擬內存地址指向庫文件所在的物理內存地址灰伟。如上文圖中所示拆又,進程P1和P2的B地址都指向了物理地址C。
而通過使用虛擬內存使用共享內存很簡單栏账,系統(tǒng)只需要將各個進程的虛擬內存地址指向系統(tǒng)分配的共享內存地址即可帖族。
SWAP
虛擬內存可以幫進程”擴充“內存。
前文提到了虛擬內存通過缺頁中斷為進程分配物理內存挡爵,內存總是有限的竖般,如果所有的物理內存都被占用完怎么辦
Linux提出SWAP的概念,Linux 中可以使用SWAP分區(qū)了讨,在分配物理內存捻激,但可用內存不足時,將暫時不用的內存數(shù)據(jù)先放到磁盤上前计,讓有需要的進程先使用胞谭,等進程再需要使用這些數(shù)據(jù)時,再將這些數(shù)據(jù)加載到內存中男杈,通過這種”交換"技術丈屹,Linux 可以讓進程使用更多的內存。
實踐和研究都證明:一個應用程序總是逐段被運行的,而且在一-段時間內會穩(wěn)定運行在某一段程序里旺垒。
這也就出現(xiàn)了一個方法:如下圖所示彩库,把要運行的那一- -段程序自輔存復制到內存中來運行,而其他暫時不運行的程序段就讓它仍然留在輔存先蒋。
當需要執(zhí)行另一端尚未在內存的程序段(如程序段2) ,如下圖所示骇钦,就可以把內存中程序段1的副本復制回輔存,在內存騰出必要的空間后竞漾,再把輔存中的程序段2復制到內存空間來執(zhí)行即可:
在計算機技術中眯搭,把內存中的程序段復制回輔存的做法叫做"換出”,而把輔存中程序段映射到內存的做法叫做"換入”业岁。經(jīng)過不斷有目的的換入和換出鳞仙,處理器就可以運行一個大于實際物理內存的應用程序了。
作者:Peanutty
鏈接:https://blog.csdn.net/hhb442/article/details/109478334
來源:CSDN
著作權歸作者所有笔时。商業(yè)轉載請聯(lián)系作者獲得授權棍好,非商業(yè)轉載請注明出處。