天天看點

記憶體映射的解釋

這個問題很大。。。。我盡自己所能給你解釋一下吧,如果你不能完全看懂,以後可以回頭再翻翻來看。關于虛拟記憶體的事情,大概是這樣的:

首先你要明确什麼是虛拟記憶體。虛拟記憶體實際上是作業系統對于記憶體管理的一種方式,比如說,對每個程式而言,它的記憶體編址都從0x00到0xff,但是實際上,這些記憶體對應的實體位址,應用程式本身是無法知道的,在這裡就可以了解成作業系統對記憶體管理的一層抽象。

比如,可能程序init的虛拟位址0x00對應了實體位址的0x10,而kthreadd的虛拟位址0x00對應實體位址0x20,etc.

而且虛拟記憶體也是一種有效的程序間隔離的方式,極大的提升了程序的安全性和作業系統的穩定性,也就是我一個程序不管做什麼,都是在它自己的位址空間裡做的,不會影響到其他程序和OS。

當然這是理想情況,實際上還有程序間通信啦之類,這就不在這個問題的範圍之内了。

而具體怎麼把這些虛拟位址對應到實體位址上,這是作業系統做的事情,估計這個也就是你的問題。

----以上是背景1-----

然後我要明确一下:位址總線4位的意思是說記憶體用4個bit位來表達位址,是以能夠index的位址位就是2^0-2^4,也就是0x0到0xf,就是16個bit的記憶體空間。

然後我們再來細化一下你的例子,就比方說在你的16bit的記憶體的機器上有1個OS,上面跑着2個程式。一般來說OS會保留位址的高位,比如11-15bit的位置,作為kernel space;然後0-10bit是user space。

在以上的前提下,虛拟記憶體的效果是:在每一個程式看來,這個程式都有0x0到0xf的位址可以用,并且它們的0xb-0xf都是shared kernel space,然後0x0-0xa都是自己的user space,這樣仿佛就有了32個bit的位址一樣。這就是你所謂的是用虛拟位址可以使總的位址操作實體位址。至于os是怎麼做到這點的,繼續往下看。

-----以上是背景2-----

作業系統對每一個程序有一個程序控制塊,叫PCB,Process Control Block,裡邊存儲了每一個程序的程序資訊,比如說寄存器,file descriptor,還有我們最關心的記憶體映射資訊。每一個程序有一個遞增的id号,叫pid,也就是Process IDentifier.

-----以上是背景3-----

程序間切換,也就是說,比如說你一個系統隻有1個CPU,但是有兩個程序要跑,而且要讓我們看起來好像是兩個程序同時在跑一樣。為什麼我要提到這個呢,後面繼續看。

-----以上是背景4-----

好,現在來講如何把虛拟位址映射到實體位址。從程式的角度來看,從malloc開始講起,比如,在某一時刻,一個程序調用了malloc,在堆(heap)上申請了2bits的空間。實際上這個行為的流程是,程式調用malloc,進入核心模式之後,調用mmap,如果成功,作業系統會從實體位址上取一塊2bits的記憶體,交給應用程式編入虛拟位址空間。更詳細一點說,每個程序對記憶體管理是一個紅黑樹的結構,也就是說,在每一個程序的PCB,裡維護了一顆紅黑樹,然後動态的将所有的新配置設定的記憶體加到這個紅黑樹裡邊,以保證程式對每一塊記憶體的通路時間是差不多的。然後不知道你們教材中有沒有提到頁表(page table),頁表也是PCB中的一項,你們教材中應該會對頁表有詳細的講解,将如何對記憶體的位址進行換算,之類的。然後你要明确,頁表實際上是紅黑樹的cache,這樣可以加速程式對于常用的記憶體的通路速度。

以上是作業系統對記憶體管理的一個大緻概括,就是一塊實體的記憶體如何映射成為一塊虛拟的記憶體。

我在背景2中說,兩個程式都看到自己有16個bit的虛拟位址,總共有32bit,但是實際上硬體隻有16bits,也就是說,不管你在紅黑樹和頁表中怎麼映射,一定會有沖突發生,比如,可能實體位址的0x02對應了程序1中的0x04,又在程序2的PCB中映射到了pid2的虛拟位址位0x06上。作業系統如何解決這個沖突呢,首先在程序pid 1運作的時候,這個0x02對應的是pid1中的0x04;然後這個時候程序切換發生了,pid 2開始運作。當pid2需要用到它的0x04時,os發現0x02這個位址在pid1中也有映射,于是它就把0x02這個位址上的内容存到硬碟上的一個叫swap的空間内,然後把這個位址交給pid2使用。這樣就達到了擴大虛拟位址的效果。

但是這樣做是有代價的,因為一旦這個page被swap出去,那麼在pid1再來調用的時候會發生一系列的miss,從L1 cache miss到 L2 cache miss到L3 cache miss,然後頁表miss,memory miss,會對程式的性能造成極大的影響。影響有多大呢,平均來說:

L1 cache hit: 0.5ns

L2 cache hit: 7ns

主記憶體引用:100ns

順序從記憶體中讀取1MB:250,000ns

硬碟尋道:10,000,000ns

從硬碟上順序讀取1MB:30,000,000ns

是以你就可以知道這種行為是以極大的性能為代價的。

----講完啦-----

總的來說這個很大的話題,我剛才所寫的東西的就是試圖讓你對虛拟記憶體這個東西有一個基本的概念,然後大緻的了解記憶體是如何映射的。就我現在能想到的,對這個虛拟記憶體話題的讨論還包括多級頁表,程序間隔離&通信以及memory fragment。