內存管理之二 linux分段與分頁

現代操做系統的內存管理機制有兩種:段式管理和頁式管理。

段式內存管理,就是將內存分紅段,每一個段的起始地址就是段基地址。地址映射的時候,由邏輯地址加上段基地址而獲得物理地址。純粹的段式內存管理的缺點很明顯,就是靈活性和效率比較差。首先是段的長度是可變的,這給內存的換入換出帶來諸多不便,如何選擇一個段的長度是一個棘手的問題;其次進程在運行過程當中,可能會擴充地址空間,這就要增長段,從而形成進程的地址空間由不少小段構成,在進程運行過程當中,訪問不一樣的段時,就須要頻繁切換段基地址;再一點,段式內存管理若是有太多的小段,在釋放段的時候,會形成外部碎片。

頁式內存管理,內存分紅固定長度的一個個頁片。地址映射的時候,須要先創建頁表,頁表中的每一項都記錄了這個頁的基地址。經過頁表,由邏輯地址的高位部分先找到邏輯地址對應的頁基地址,再由頁基地址偏移必定長度就獲得最後的物理地址,偏移的長度由邏輯地址的低位部分決定。通常狀況下,這個過程均可以由硬件完成,因此效率仍是比較高的。頁式內存管理的優勢就是比較靈活,內存管理以較小的頁爲單位,方便內存換入換出和擴充地址空間。

操作系統

嚴格說Linux採用段頁式內存管理,也就是既分段,又分頁。地址映射的時候,先肯定對應的段,肯定段基地址;段內分頁,再找到對應的頁表項,肯定頁基地址;再由邏輯地址低位肯定的頁偏移量,就能找到最終的物理地址。可是,實際上Linux採用的是頁式內存管理。緣由是Linux中的段基地址都是0,至關於全部的段都是相同的。這樣作的緣由是某些體系結構的硬件限制,好比Intel的i386。做爲軟件的操做系統,必需要符合硬件體系。雖然全部段基地址都是0,可是段的概念在Linux內核中是確實存在的。好比常見的內核代碼段、內核數據段、用戶態代碼段、用戶態數據段等。除了符合硬件要求外,段也是有實際意義的。指針

邏輯地址分爲兩部分組成:段標識符和指定段內相對地址的偏移量。
段描述符:用來存放段起始地址,段大小,存儲權限等。
段描述符表:存放段描述的表項。
段寄存器:存放段標識符。6個段寄存器稱爲cs(代碼段寄存器),ss(棧段寄存器),ds(數據段寄存器),es,fs 和gs。
段基地址寄存器:指向段描述符表地址。


Linux分段機制:
Linux對分段使用很是有限。做爲一個跨硬件體系的操做系統,要支持多種硬件體系,而一些硬件體系結構式不支持分段的,Linux把全部段起始地址都設爲0。
Linux採用4個段進行尋址,用戶態代碼段,用戶態數據段,內核態代碼段,內核態數據段。索引

 

x86採用兩級頁表。
第一級爲頁目錄表,存儲在一個4K字節的頁中,每一個表項包含了一個頁表的物理地址。線性地址最高的10位(22-31)用來產生第一級表索引,由該索引獲得的表項中的內容定位了二級表中的一個表的地址,即下級頁表所在的內存塊號。
第二級爲頁表,存儲在一個4K字節頁中,每一個表項包含了一個頁的物理地址。線性地址的中間10位(12-21)位進行索引,定位頁表表項,得到頁的物理地址。頁物理地址的高20位與線性地址的低12位造成最後的物理地址。進程

分頁機制由CR0寄存器中的PG位啓用。如PG=1,啓用分頁機制,把線性地址轉換爲物理地址。如PG=0,禁用分頁機制,直接段機制產生的線性地址看成物理地址使用。
頁目錄表的物理地址存放在CR3寄存器。每一個進程有它本身的頁全局目錄和本身的頁表集。當發生進程切換時,Linux把CR3控制寄存器的內容保存在前一個執行進程的描述符中,而後把下一個要執行進程的描述符的值裝入CR3寄存器中。這確保了當新進程從新開始在CPU上執行時,分頁單元指向一組正確的頁表。
Linux分頁機制:
做爲一個通用的操做系統,Linux須要兼容各類硬件體系,包括不一樣位數的CPU。對64位的CPU來講,兩級頁表仍然太少,一個頁表會太大,這會佔用太多寶貴的物理內存。Linux採用了通用的四級頁表。實際採用幾級頁表則具體受硬件的限制。

 

四種頁表分別稱爲: 頁全局目錄、頁上級目錄、頁中間目錄、頁表。對於32位x86系統,兩級頁表已經足夠了。Linux經過使「頁上級目錄」位和「頁中間目錄」位全爲0,完全取消了頁上級目 錄和頁中間目錄字段。不過,頁上級目錄和頁中間目錄在指針序列中的位置被保留,以便一樣的代碼在32位系統和64位系統下都能使用。內存

 

邏輯地址分爲兩部分組成:段標識符和指定段內相對地址的偏移量。
段描述符:用來存放段起始地址,段大小,存儲權限等。 段描述符表:存放段描述的表項。 段寄存器:存放段標識符。6個段寄存器稱爲cs(代碼段寄存器),ss(棧段寄存器),ds(數據段寄存器),es,fs 和gs。 段基地址寄存器:指向段描述符表地址。
相關文章
相關標籤/搜索