在早期的計(jì)算機(jī)中,程序是直接運(yùn)行在物理內(nèi)存上的,也就是說(shuō):程序在運(yùn)行時(shí)訪問(wèn)的地址就是物理地址。這樣也就是單運(yùn)行的時(shí)候沒(méi)有什么問(wèn)題!可是,計(jì)算機(jī)會(huì)有多到程序、分時(shí)系統(tǒng)和多任務(wù),當(dāng)我們能夠同時(shí)運(yùn)行多個(gè)程序時(shí),
CPU的利用率將會(huì)比較高。那么有一個(gè)非常嚴(yán)重的問(wèn)題:如何將計(jì)算機(jī)的有限的物理內(nèi)存分配給多個(gè)程序使用
假設(shè)我們計(jì)算有128MB內(nèi)存,程序A需要10MB,程序B需要100MB,程序C需要20MB。如果我們需要同時(shí)運(yùn)行程序A和B,那么比較直接的做法是將內(nèi)存的前10MB分配給程序A,10MB~110MB分配給B。

但這樣做,會(huì)造成以下問(wèn)題:
當(dāng)多個(gè)程序需要運(yùn)行時(shí),必須保證這些程序用到的內(nèi)存總量要小于計(jì)算機(jī)實(shí)際的物理內(nèi)存的大小。
進(jìn)程地址空間不隔離,由于程序是直接訪問(wèn)物理內(nèi)存的,所以每一個(gè)進(jìn)程都可以修改其他進(jìn)程的內(nèi)存數(shù)據(jù),設(shè)置修改內(nèi)核地址空間中的數(shù)據(jù),所以有些惡意程序可以隨意修改別的進(jìn)程,就會(huì)造成一些破壞
內(nèi)存使用效率低 內(nèi)存空間不足,就需要將其他程序展示拷貝到硬盤(pán)當(dāng)中,然后將新的程序裝入內(nèi)存。然而由于大量的數(shù)據(jù)裝入裝出,內(nèi)存的使用效率會(huì)非常低
程序運(yùn)行的地址不確定;因?yàn)閮?nèi)存地址是隨機(jī)分配的,所以程序運(yùn)行的地址也是不正確的
解決這幾個(gè)問(wèn)題的思路就是使用我們非常牛逼的方法:增加中間層 - 即使用一種間接的地址訪問(wèn)方式。
把程序給出的地址看做是一種虛擬地址,然后通過(guò)某種映射,將這個(gè)虛擬地址轉(zhuǎn)化到實(shí)際的物理地址。這樣,只需要控制好映射過(guò)程,就能保證程序所能訪問(wèn)的物理內(nèi)存區(qū)域跟別的程序不重疊,達(dá)到空間隔離的效果。
隔離
普通的程序它只需要一個(gè)簡(jiǎn)單的執(zhí)行環(huán)境,一個(gè)單一的地址空間,有自己的CPU。
地址空間比較抽象,如果把它想象成一個(gè)數(shù)組,每一個(gè)數(shù)組是一字節(jié),數(shù)組大小就是地址空間的長(zhǎng)度,那么32位的地址空間大小就是2^32=4294967296字節(jié),即4G,地址空間有效位是0x00000000~0xFFFFFFFF。
地址空間分為兩種:
物理空間:就是物理內(nèi)存。32位的機(jī)器,地址線就有32條,物理空間4G,但如果只裝有
512M的內(nèi)存,那么實(shí)際有效的空間地址就是0x00000000~0x1FFFFFFF,其他部分都是無(wú)效的。虛擬空間:每個(gè)進(jìn)程都有自己獨(dú)立的虛擬空間,而且每個(gè)進(jìn)程只能訪問(wèn)自己的空間地址,這樣就有效的做到了進(jìn)程隔離。
分段
基本思路: 把一段與程序所需要的內(nèi)存空間大小的虛擬空間映射到某個(gè)地址空間。虛擬空間的每個(gè)字節(jié)對(duì)應(yīng)物理空間的每個(gè)字節(jié)。這個(gè)映射過(guò)程由軟件來(lái)完成。
比如A需要10M,就假設(shè)有0x00000000 到0x00A00000大小的虛擬空間,然后從物理內(nèi)存分配一個(gè)相同大小的空間,比如是0x00100000到0x00B00000。操作系統(tǒng)來(lái)設(shè)置這個(gè)映射函數(shù),實(shí)際的地址轉(zhuǎn)換由硬件完成。如果越界,硬件就會(huì)判斷這是一個(gè)非法訪問(wèn),拒絕這個(gè)地址請(qǐng)求,并上報(bào)操作系統(tǒng)或監(jiān)控程序。

這樣一來(lái)利用分段的方式可以解決之前的地址空間不隔離和程序運(yùn)行地址不確定
首先做到了地址隔離,因?yàn)锳和B被映射到了兩塊不同的物理空間,它們之間沒(méi)有任何重疊,如果A訪問(wèn)虛擬空間的地址超過(guò)了
0x00A00000這個(gè)范圍,硬件就會(huì)判斷這是一個(gè)非法的訪問(wèn),并將這個(gè)請(qǐng)求報(bào)告給操作系統(tǒng)或者監(jiān)控程序,由它決定如何處理。再者,對(duì)于每個(gè)程序來(lái)說(shuō),無(wú)論它們被分配到地址空間的哪一個(gè)區(qū)域,對(duì)于程序來(lái)說(shuō)都是透明的,它們不需要關(guān)心物理地址的變化,它們只要按照從地址
0x00000000到0x00A00000來(lái)編寫(xiě)程序、放置變量,所以程序不需要重定位。
第二問(wèn)題內(nèi)存使用效率問(wèn)題依舊沒(méi)有解決。
但是分段的方法沒(méi)有解決內(nèi)存使用效率的問(wèn)題。分段對(duì)于內(nèi)存區(qū)域的映射還是按照程序?yàn)閱挝?,如果?nèi)存不足,被換入換出的磁盤(pán)的都是整個(gè)程序,這樣勢(shì)必會(huì)造成大量的磁盤(pán)訪問(wèn)操作,從而嚴(yán)重影響速度,這種方法還是顯得粗糙,粒度比較大。事實(shí)上根據(jù)程序的局部性原理,當(dāng)一個(gè)程序正在運(yùn)行時(shí),在某個(gè)時(shí)間段內(nèi),它只是頻繁用到了一小部分?jǐn)?shù)據(jù),也就是說(shuō),程序的很多數(shù)據(jù)其實(shí)在一個(gè)時(shí)間段內(nèi)是不會(huì)被用到的。人們很自然地想到了更小粒度的內(nèi)存分割和映射方法,使得程序的局部性原理得到充分利用,大大提高了內(nèi)存的使用率。這種方法就是分頁(yè)。
分頁(yè)
分頁(yè)的基本方法是把地址空間人為得等分成固定大小的頁(yè),每一個(gè)頁(yè)的大小由硬件決定,或硬件支持多種頁(yè)的大小,由操作系統(tǒng)選擇決定頁(yè)的大小。 目前幾乎所有PC的操作系統(tǒng)都是用4KB大小的頁(yè)。我們使用的PC機(jī)是32位虛擬地址空間,也就是4GB,按4KB分頁(yè),總共有1048576個(gè)頁(yè)。
那么,當(dāng)我們把進(jìn)程的虛擬地址空間按頁(yè)分割,把常用的數(shù)據(jù)和代碼裝載到內(nèi)存中,把不常用的代碼和數(shù)據(jù)保存在磁盤(pán)里,當(dāng)需要用到的時(shí)候再把它們從磁盤(pán)里取出即可。圖中的線表示映射關(guān)系,我們可以看到虛擬空間有些頁(yè)被映射到同一個(gè)物理頁(yè),這樣就可以實(shí)現(xiàn)內(nèi)存共享。
虛擬頁(yè),物理頁(yè),磁盤(pán)頁(yè)根據(jù)內(nèi)存空間不一樣而區(qū)分
我們可以看到Process 1 的VP2和VP3不在內(nèi)存中,但是當(dāng)進(jìn)程需要用到這兩個(gè)頁(yè)的時(shí)候,硬件就會(huì)捕獲到這個(gè)消息,就是所謂的頁(yè)錯(cuò)誤(Page Fault),然后操作系統(tǒng)接管進(jìn)程,負(fù)責(zé)將VP2和VP3從磁盤(pán)讀取出來(lái)裝入內(nèi)存,然都將內(nèi)存中的這兩個(gè)頁(yè)和VP2和VP3建立映射關(guān)系。以頁(yè)為單位存取和交換數(shù)據(jù)非常方便,硬件本身就支持這種以頁(yè)為單位的操作方式。

保護(hù)頁(yè)也是頁(yè)映射的目的之一,簡(jiǎn)單地說(shuō)就是每個(gè)頁(yè)可以設(shè)置權(quán)限屬性,誰(shuí)可以修改,誰(shuí)可以訪問(wèn),而且只有操作系統(tǒng)有權(quán)修改這些屬性,那么操作系統(tǒng)就可以做到保護(hù)自己和保護(hù)進(jìn)程。
虛擬存儲(chǔ)的實(shí)現(xiàn)需要硬件支持,幾乎所有CPU都采用稱(chēng)為MMU的部件來(lái)進(jìn)行頁(yè)的映射:

在頁(yè)映射模式下,CPU發(fā)出的是Virtual Address,即我們程序看到的是虛擬地址。經(jīng)過(guò)MMU轉(zhuǎn)換以后就變成了Physical Address。一般MMU集成在CPU內(nèi)部,不會(huì)以獨(dú)立的部件存在。
作者:Cooci_和諧學(xué)習(xí)_不急不躁
鏈接:http://www.itdecent.cn/p/1ad04daa1b8a
來(lái)源:簡(jiǎn)書(shū)
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。