首先先回顧了下cpu的LDE模式的思路,主要就是在大多數時間讓程序直接在硬體上運行,但是在一些關鍵功能上,比如硬體訪問,進程調度上能夠讓os得到控制,從而實現了高效運行的同時也能保證對系統的控制

這一章要說的內存控制也是一樣的思路,我們需要一些基本的硬體的支持,在這之上讓os能夠高效的實現vm.並且我們實現的vm也是需要有很好的擴展性,因為對程序來說,內存的變化是非常頻繁的。

為了實現vm,我們會使用到地址翻譯,也就是說程序看到的內存地址都是虛擬的,而實際的物理地址是由os來掌握的,當然單憑硬體是無法虛擬的,硬體只是提供了實現的基本支持,需要os會運用物理硬體的功能,加上軟體的管理來記錄實際物理地址的使用情況,提供對應的分配和回收內存的功能,從而實現在對內存加以控制的情況下的高效的虛擬化。

再次強調,我們要做的是實現一個美好的假象:讓每個進程都能看到自己獨立的,並且大小一致的地址空間。在這之下的各種盤根錯節的處理都由os來進行。

首先從最基本的說起,我們先做幾個簡單的假設:

1.用戶的地址空間在物理內存中是連續存儲的

2.地址空間的大小不會大於物理內存

3.假設地址空間都是相等大小的

首先我們來介紹一種動態分配地址空間的方式:

比如這段代碼

128: movl 0x0(%ebx), %eax ; load 0+ebx into eax

132: addl $0x03, %eax ; add 3 to eax register

135: movl %eax, 0x0(%ebx) ; store eax back to mem

如果要運行這個程序,首先需要載入到內存,這些代碼的地址就是上面彙編代碼最前面的數字。當要運行的時候,

1.先去地址為128處取出指令,然後執行,這條指令是按照寄存器ebx的內容作為地址,將地址空間中對應的內容取出放在寄存器eax中,假設ebx的內容是15K,那麼從15k處取到了3000。

2.取出132處的指令,將eax中的數據加3,這樣就變為了3003

3.取出135處的指令,將eax中的3003放到ebx指向的位置,也就是15K的地方,這樣15K這個地址的數據就從3000變為了3003

上面看到的是這個進程的地址空間的信息,那麼在整個系統中是什麼樣呢,答案就是下面這張圖

從上圖分配中可以看到,os在最開始的16KB中,我們上面所說的有三行代碼的程序實際上是放在32KB到48KB這個區間段內的。代碼中的地址是虛擬的,所以實際的地址是虛擬地址加上32KB的。這個也是個通用的模式:

物理地址=基地址+虛擬地址

所以cpu在執行每條指令的時候,實際都需要進行一個從虛擬地址到物理地址翻譯的步驟,這個功能由一個單獨的硬體完成,我們稱之為MMU(memory management unit)。對於上面動態分配內存,我們需要2個寄存器來輔助完成地址翻譯的過程,分別是基地址寄存器和界限寄存器(base and bound)。base 存儲這個process 對應的基地址,bound存儲地址空間的大小。

下面我們總結一下,為了完成上面的這種內存動態的分配,我們需要硬體和OS的哪些功能支持。

硬體模塊提供的功能:

1.cpu提供特權模式和一般模式。這樣就可以形成一種保護的機制,用戶的process無法執行一些特權指令,從而讓os能夠對內存的實際管理得到控制。

2.base and bound register。這個上面說過,在翻譯地址的時候用到。

3.有進行地址轉換和校驗的功能。也就是不僅要有上面說的寄存器,還要有用到這些寄存器的功能,也就是拿到一個虛擬的地址能有專門的硬體進行轉換從而得到實際的物理地址。

4.提供特權指令對base and bound register 進行修改。

5.如果發生異常,需要特權指令來觸發異常處理告訴os。

操作系統提供的功能:

1.對物理內存的管理,比如分配新內存,回收就內存等等。

2.在process 切換的時候能夠更新base and bound 寄存器的內容

3.收到硬體的異常能對異常情況的處理(也就是os有些對應的代碼,還記得之前說的trap table嗎?)。

最後在書中有一個整體的流程圖,理解這個很重要。

這個圖是在之前加入時鐘中斷後的流程圖的進一步擴充,主要就是加入了address translation的步驟,注意這個步驟是硬體自動完成的。


推薦閱讀:
相关文章