MIT6.828——Lab1 PartA
MIT6.828——Lab1 PartB
分段的主要問題,出現在記憶體不足或者記憶體碎片過多的情況下。對于一個程式而言,例如其代碼段長度就和其代碼的長度直接相關,各個段的大小是不固定的,不能拆分的,要裝入記憶體便一次性将一個整段都裝入,是以在記憶體緊張時,就會出現問題。可以想象到的解決方法有這樣一種:将段換出到磁盤上,進而空出一部分的實體記憶體空間。但是同樣的,如果段長度過長,記憶體過小,在頻繁的換入換出也無濟于事。
問題的本質在于,分段機制下産生的連續線性位址,被認為在實體記憶體上也是連續的,線性位址就是實體位址。但是我們可用的實體位址并不是連續的,是以就會産生沖突。是以解決這個問題的關鍵在于,是否可以:線性位址連續,對應的實體位址不連續?為了解除這種一一映射的關系,便可以通過位址映射。
即 線性位址(虛拟位址)——頁表——> 實體位址。
為了效率的問題,這種映射關系寫在頁表裡,頁表在記憶體中,查表的工作由硬體完成。
分頁機制的思想:通過映射,可以使得連續的線性位址與任意的實體位址相關聯,邏輯上連續的線性位址對應的實體位址可以不連續。
分段機制的作用:将線性位址轉化為實體位址;用大小相等(4KB)的頁代替大小不等的段。
首先針對一級頁表而言,尋址過程可以由下圖表示
可以看到,分頁機制仍舊是基于分段基礎上的。将分段形成的線性位址,進行劃分,利用高20位作為在頁表内尋址的偏移量,尋址頁表項,其中頁表項的基址(實體位址)放在CR3寄存器中。再利用低12位,結合頁表項給出的基址,合成實體位址,送上位址總線,即可尋址實體記憶體單元。可以看到,因為劃分了低12位為頁内偏移,是以頁表的大小也就是4KB,這是一個常用的頁大小值。而高20位,則說明,頁表中含1M項頁表項,占記憶體位4MB。
在一級頁表的鋪墊下,便有了另一個問題。頁表的大小為4M,且必須提前建立好,每個程序都有自己的頁表,如果程序數很多,頁表的記憶體開銷便很可觀,是以是否可以動态的建立頁表項呢?解決這個問題的答案就是二級頁表。二級頁表的思想是,将1M頁平均放到1K個頁表中,每個頁表1K個頁表項,占據記憶體位4KB,剛好為一頁的大小。為了存儲這些頁表,引入了頁目錄。每個頁表的實體位址,都在頁目錄中以頁目錄項的形式存儲。因為最多1K頁表,是以頁目錄大小也為4KB,一頁的大小。
二級頁表下的尋址過程如下:
現在需要了解一下,頁表項和頁目錄項的詳細資訊了。這部分資訊,可以在Intel系統開發手冊上得到詳細說明。
這裡直接截取部分說明了:
開啟分頁機制,需要做三件事:
準備好頁表和頁目錄
将頁目錄的實體位址寫入CR3
寄存器CR0的PG位置1
在之前的<code>mit6.828</code>實驗1中,已經看到了一個比較基本的執行個體,如何進入保護模式,并進行分頁操作。為了對于<code>lab2</code>有一個更好的了解,這裡截取一部分《作業系統真象還原》的代碼進行解釋說明。這裡可以和<code>lab1</code>部分結合來看
按約定,GDT的第一個段描述符為空,這裡建立了三個段,都是按照段描述符的規格進行性質填充,對照相關位的含義既可以知道段的資訊。為了裝載GDT,使用指令<code>lgdt</code>即可。進入保護模式後,尋址就需要使用段選擇子,這在之前的<code>lab1</code>中也說到了。
首先規劃記憶體的整體布局,可以先畫出下面這張圖
人為規定的,将頁目錄放在了實體位址<code>0x100000</code>處,将第一個頁表,放在了實體位址<code>0x101000</code>處。同時劃分程序的虛拟位址空間位高端<code>1GB</code>核心空間和低端<code>3GB</code>使用者控件。首先需要注意的是,在虛拟記憶體空間中,将高端<code>1GB</code>完全分給了核心。這對于每個程序都是一樣的,為了實作所有程序的核心共享,這部分空間固定占據了頁目錄項的第<code>0xc00</code>項至第<code>1023</code>項。對于頁目錄而言,第<code>0</code>項存儲了第<code>0</code>個頁表的位置,最後一項存儲了頁目錄自身在實體記憶體中的位置。
值得注意的是,頁表<code>0</code>和頁表<code>c00</code>都映射到了實體記憶體的低端<code>1MB</code>。這麼做的原因是,在核心加載到記憶體空間之前,運作的一直是<code>loader</code>程式,它運作在低端<code>1MB</code>。為了保證之前段機制下的位址和現在分頁後的位址一緻,核心的前<code>1MB</code>也需要映射到實體記憶體低端<code>1MB</code>空間。低端的<code>1MB=256*4KB</code>,是以占據了<code>256</code>頁,需要<code>256</code>個頁表項。
在這部分說明之後,下面便是具體的實作:
在建立好了虛拟記憶體的布局之後,就可以正式開啟分頁機制