小編給大家分享一下Linux需要虛擬內(nèi)存的原因有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
創(chuàng)新互聯(lián),專注為中小企業(yè)提供官網(wǎng)建設(shè)、營銷型網(wǎng)站制作、響應(yīng)式網(wǎng)站、展示型成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)等服務(wù),幫助中小企業(yè)通過網(wǎng)站體現(xiàn)價值、有效益。幫助企業(yè)快速建站、解決網(wǎng)站建設(shè)與網(wǎng)站營銷推廣問題。
在回答虛擬內(nèi)存存在的必要性之前,我們需要理解操作系統(tǒng)中的虛擬內(nèi)存是什么,它在操作系統(tǒng)中起到什么樣的作用。正如軟件工程中的其他抽象,虛擬內(nèi)存是操作系統(tǒng)物理內(nèi)存和進程之間的中間層,它為進程隱藏了物理內(nèi)存這一概念,為進程提供了更加簡潔和易用的接口以及更加復(fù)雜的功能。
virtual-memory-layer
圖 1 - 進程和操作系統(tǒng)的中間層
如果需要我們從頭設(shè)計一個操作系統(tǒng),讓系統(tǒng)中的進程直接訪問主內(nèi)存中的物理地址應(yīng)該是非常自然的決定,早期的操作系統(tǒng)確實也都是這么實現(xiàn)的,進程會使用目標(biāo)內(nèi)存的物理地址(Physical Address)直接訪問內(nèi)存中的內(nèi)容,然而現(xiàn)代的操作系統(tǒng)都引入了虛擬內(nèi)存,進程持有的虛擬地址(Virtual Address)會經(jīng)過內(nèi)存管理單元(Memory Mangament Unit)的轉(zhuǎn)換變成物理地址[^2],然后再通過物理地址訪問內(nèi)存:
virtual-memory-system
圖 2 - 虛擬內(nèi)存系統(tǒng)
主存儲是相對比較稀缺的資源,雖然順序讀取只比磁盤快 1 個數(shù)量級,但是它能提供極快的隨機訪問速度,從內(nèi)存上隨機讀取數(shù)據(jù)是磁盤的 100,000 倍[^3],充分利用內(nèi)存的隨機訪問速度是改善程序執(zhí)行效率的有效方式。
操作系統(tǒng)以頁為單位管理內(nèi)存,當(dāng)進程發(fā)現(xiàn)需要訪問的數(shù)據(jù)不在內(nèi)存時,操作系統(tǒng)可能會將數(shù)據(jù)以頁的方式加載到內(nèi)存中,這個過程是由上圖中的內(nèi)存管理單元(MMU)完成的。操作系統(tǒng)的虛擬內(nèi)存作為一個抽象層,起到了以下三個非常關(guān)鍵的作用:
虛擬內(nèi)存可以利用磁盤起到緩存的作用,提高進程訪問指定內(nèi)存的速度;
虛擬內(nèi)存可以為進程提供獨立的內(nèi)存空間,簡化程序的鏈接、加載過程并通過動態(tài)庫共享內(nèi)存;
虛擬內(nèi)存可以控制進程對物理內(nèi)存的訪問,隔離不同進程的訪問權(quán)限,提高系統(tǒng)的安全性;
緩存
我們可以將虛擬內(nèi)存看作是在磁盤上一片空間,當(dāng)這片空間中的一部分訪問比較頻繁時,該部分?jǐn)?shù)據(jù)會以頁為單位被緩存到主存中以加速 CPU 訪問數(shù)據(jù)的性能,虛擬內(nèi)存利用空間較大的磁盤存儲作為『內(nèi)存』并使用主存儲緩存進行加速,讓上層認為操作系統(tǒng)的內(nèi)存很大而且很快,然而區(qū)域很大的磁盤并不快,而很快的內(nèi)存也并不大。
virtual-memory-cache
圖 3 - 虛擬內(nèi)存、主存和磁盤
虛擬內(nèi)存中的虛擬頁(Virtual Page,PP)可能處于以下的三種狀態(tài) — 未分配(Unallocated)、未緩存(Uncached)和已緩存(Cached),其中未分配的內(nèi)存頁是沒有被進程申請使用的,也就是空閑的虛擬內(nèi)存,不占用虛擬內(nèi)存磁盤的任何空間,未緩存和已緩存的內(nèi)存頁分別表示已經(jīng)加載到主存中的內(nèi)存頁和僅加載到磁盤中的內(nèi)存頁。如上圖所示,圖中綠色的虛擬內(nèi)存頁由主存中的物理內(nèi)存頁(Physical Page,PP)支撐,所以它是已經(jīng)緩存過的,而黃色的虛擬內(nèi)存頁僅在磁盤中,所以沒有被物理內(nèi)存緩存。
當(dāng)用戶程序訪問未被緩存的虛擬頁時,硬件就會觸發(fā)缺頁中斷(Page Fault,PF),在部分情況下,被訪問的頁面已經(jīng)加載到了物理內(nèi)存中,但是用戶程序的頁表(Page Table)并不存在該對應(yīng)關(guān)系,這時我們只需要在頁表中建立虛擬內(nèi)存到物理內(nèi)存的關(guān)系;在其他情況下,操作系統(tǒng)需要將磁盤上未被緩存的虛擬頁加載到物理內(nèi)存中[^4]。
page-fault
圖 4 - 虛擬內(nèi)存的缺頁中斷
因為主內(nèi)存的空間是有限的,當(dāng)主內(nèi)存中不包含可以使用的空間時,操作系統(tǒng)會從選擇合適的物理內(nèi)存頁驅(qū)逐回磁盤,為新的內(nèi)存頁讓出位置,選擇待驅(qū)逐頁的過程在操作系統(tǒng)中叫做頁面替換(Page Replacement)。缺頁中斷和頁面替換技術(shù)都是操作系統(tǒng)調(diào)頁算法(Paging)的一部分,該算法的目的就是充分利用內(nèi)存資源作為磁盤的緩存以提高程序的運行效率。
內(nèi)存管理
虛擬內(nèi)存可以為正在運行的進程提供獨立的內(nèi)存空間,制造一種每個進程的內(nèi)存都是獨立的假象,在 64 位的操作系統(tǒng)上,每個進程都會擁有 256 TiB 的內(nèi)存空間,內(nèi)核空間和用戶空間分別占 128 TiB[^5],部分操作系統(tǒng)使用 57 位虛擬地址以提供 128 PiB 的尋址空間[^6]。因為每個進程的虛擬內(nèi)存空間是完全獨立的,所以它們都可以完整的使用 0x0000000000000000 到 0x00007FFFFFFFFFFFF 的全部內(nèi)存。
virtual-memory-space
圖 5 - 操作系統(tǒng)的虛擬內(nèi)存空間
虛擬內(nèi)存空間只是操作系統(tǒng)中的邏輯結(jié)構(gòu),就像我們上面說的,應(yīng)用程序最終還是需要訪問物理內(nèi)存或者磁盤上的內(nèi)容。因為操作系統(tǒng)加了一個虛擬內(nèi)存的中間層,所以我們也需要為進程實現(xiàn)地址翻譯器,實現(xiàn)從虛擬地址到物理地址的轉(zhuǎn)換,頁表是虛擬內(nèi)存系統(tǒng)中的重要數(shù)據(jù)結(jié)構(gòu),每一個進程的頁表中都存儲了從虛擬內(nèi)存到物理內(nèi)存頁的映射關(guān)系,為了存儲 64 位操作系統(tǒng)中 128 TiB 虛擬內(nèi)存的映射數(shù)據(jù),Linux 在 2.6.10 中引入了四層的頁表輔助虛擬地址的轉(zhuǎn)換[^7],在 4.11 中引入了五層的頁表結(jié)構(gòu)[^8],在未來還可能會引入更多層的頁表結(jié)構(gòu)以支持 64 位的虛擬地址。
four-level-page-tables
圖 6 - 四層頁表結(jié)構(gòu)
在如上圖所示的四層頁表結(jié)構(gòu)中,操作系統(tǒng)會使用最低的 12 位作為頁面的偏移量,剩下的 32 位會分四組分別表示當(dāng)前層級在上一層中的索引,所有的虛擬地址都可以用上述的多層頁表查找到對應(yīng)的物理地址。
因為有多層的頁表結(jié)構(gòu)可以用來轉(zhuǎn)換虛擬地址,所以多個進程可以通過虛擬內(nèi)存共享物理內(nèi)存。我們在 為什么 redis 快照使用子進程 一文中介紹的寫時復(fù)制就利用了虛擬內(nèi)存的這個特性,當(dāng)我們在 Linux 中調(diào)用 fork 創(chuàng)建子進程時,實際上只復(fù)制了父進程的頁表。如下圖所示,父子進程會通過不同的頁表指向相同的物理內(nèi)存:
process-shared-memory
圖 7 - 進程間共享內(nèi)存
虛擬內(nèi)存不僅可以在 fork 時用于共享進程的物理內(nèi)存,提供寫時復(fù)制的機制,還能共享一些常見的動態(tài)庫減少物理內(nèi)存的占用,所有的進程都可能調(diào)用相同的操作系統(tǒng)內(nèi)核代碼,而 C 語言程序也會調(diào)用相同的標(biāo)準(zhǔn)庫。
除了能夠共享內(nèi)存之外,獨立的虛擬內(nèi)存空間也會簡化內(nèi)存的分配過程,當(dāng)用戶程序向操作系統(tǒng)申請堆內(nèi)存時,操作系統(tǒng)可以分配幾個連續(xù)的虛擬頁,但是這些虛擬頁可以對應(yīng)到物理內(nèi)存中不連續(xù)的頁中。
內(nèi)存保護
操作系統(tǒng)中的用戶程序不應(yīng)該修改只讀的代碼段,也不應(yīng)該讀取或者修改內(nèi)核中的代碼和數(shù)據(jù)結(jié)構(gòu)或者訪問私有的以及其他的進程的內(nèi)存,如果無法對用戶進程的內(nèi)存訪問進行限制,攻擊者就可以訪問和修改其他進程的內(nèi)存影響系統(tǒng)的安全。
如果每一個進程都持有獨立的虛擬內(nèi)存空間,那么虛擬內(nèi)存中頁表可以理解成進程和物理頁的『連接表』,其中可以存儲進程和物理頁之間的訪問關(guān)系,包括讀權(quán)限、寫權(quán)限和執(zhí)行權(quán)限:
virtual-memory-permission
圖 8 - 讀權(quán)限、寫權(quán)限和執(zhí)行權(quán)限
內(nèi)存管理單元可以決定當(dāng)前進程是否有權(quán)限訪問目標(biāo)的物理內(nèi)存,這樣我們就最終將權(quán)限管理的功能全部收斂到虛擬內(nèi)存系統(tǒng)中,減少了可能出現(xiàn)風(fēng)險的代碼路徑。
總結(jié)
虛擬內(nèi)存的設(shè)計方法可以說是軟件工程中的常見手段,通過結(jié)合磁盤和內(nèi)存各自的優(yōu)勢,利用中間層對資源進行更合理地調(diào)度充分提高資源的利用率并提供和諧以及統(tǒng)一的抽象,而在實際的業(yè)務(wù)場景中,類似的緩存邏輯也比較常見。
操作系統(tǒng)的虛擬內(nèi)存是非常復(fù)雜的組件,沒有工程師能夠了解其中的全部細節(jié),不過了解虛擬內(nèi)存的整體設(shè)計也很有價值,我們能夠從中找到很多軟件設(shè)計的方法。我們重新回到今天的問題 — Linux 操作系統(tǒng)中為什么需要虛擬內(nèi)存:
虛擬內(nèi)存可以結(jié)合磁盤和物理內(nèi)存的優(yōu)勢為進程提供看起來速度足夠快并且容量足夠大的存儲;
虛擬內(nèi)存可以為進程提供獨立的內(nèi)存空間并引入多層的頁表結(jié)構(gòu)將虛擬內(nèi)存翻譯成物理內(nèi)存,進程之間可以共享物理內(nèi)存減少開銷,也能簡化程序的鏈接、裝載以及內(nèi)存分配過程;
虛擬內(nèi)存可以控制進程對物理內(nèi)存的訪問,隔離不同進程的訪問權(quán)限,提高系統(tǒng)的安全性;
以上是“Linux需要虛擬內(nèi)存的原因有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
分享文章:Linux需要虛擬內(nèi)存的原因有哪些
新聞來源:http://www.chinadenli.net/article46/joijhg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、網(wǎng)站收錄、網(wǎng)站內(nèi)鏈、網(wǎng)站制作、動態(tài)網(wǎng)站、App設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)