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