2Linux內存佈局

在上一篇博文裏,我們已經看到Linux如何有效地利用80x86的分段和分頁硬件單元把邏輯地址轉換爲線性地址,在由線性地址轉換到物理地址。那麼我們的應用程序如何使用這些邏輯地址,整個內存的地址佈局又是怎樣的?打一個比方,內存就像一座城市,而居住在這個城市裏的市民就像是各個進程,一個市民喫喝拉撒睡,當然就得用於“房子”、“車子”、“票子”等各種各樣的資源。有些資源是固定的,如“房子”,我們稱之爲靜態數據;有些資源是動態的,如“車子”,我們稱之爲動態數據;有些資源是用來購買(產生)數據的,如“票子”,我們稱之爲代碼。

現在,我們就來看看內存這座巨大的城市史如何佈局的。在系統初始化階段,內核首先在實模式下建立一個物理地址映射來指定哪些物理地址範圍對內核可用而哪些不可用(主要是根據映射硬件設備I/O的共享內存,或者根據相應的頁框含有的BIOS數據)。

內存的某些部分將永久地分配給BOIS或內核,用來存放BIOS信息、內核代碼以及靜態內核數據結構。所以內核將下列頁框記爲保留:
• 在不可用的物理地址範圍內的頁框,一般用來存放BIOS信息。
• 含有內核代碼和已初始化的數據結構的頁框。

標記爲保留頁框中的頁,絕不能被動態分配或交換到磁盤上。

一般來說,Linux內核安裝在RAM中從物理地址0x00100000開始的地方,也就是說,從第二個MB開始。所需頁框總數依賴於內核的配置方案:典型的配置所得到的內核可以完全被安裝在小於3MB的RAM中。

爲什麼內核沒有安裝在RAM第一個MB開始的地方?主要是爲具體的PC體系結構所考慮。例如:
• 頁框0由BIOS使用,存放加電自檢(Power-On Self-Test,POST)期間檢查到的硬件配置。因此,很多膝上型電腦的BIOS甚至在系統初始化後還將數據寫到該頁框。
• 物理地址從0x000a0000 到 0x000fffff的範圍通常留給BIOS例程,並且映射ISA圖形卡上的內部存儲器。這個區域就是所有IBM兼容PC上從640KB到1MB之間著名的洞:物理地址存在但被保留,對應的頁框不能由操作系統使用。
• 前1MB內的其他頁框可能由特定計算機模型保留。例如,IBM 筆記本電腦把0x0a頁框映射到0x9f頁框。

在啓動過程的早期階段,內核詢問BIOS並瞭解物理內存的大小,並調用machine_specific_memory_setup()函數建立物理地址映射。假設我們的內存是128MB,那麼,第一個MB就給BIOS了。整個128MB的內存被物理映射成以下佈局:
0x00000000   -   0x0009ffff     除第一個頁框外的640K空間可用
0x000a0000   -   0x000effff     保留
0x000f0000   -   0x000fffff     保留給BIOS例程
0x00100000   -   0x07feffff     126.9MB可用空間
0x07ff0000   -   0x07ff2fff     ACPI data
0x07ff3000   -   0x07ffffff     ACPI NVS
0xffff0000   -   0xffffffff     保留
這裏簡單介紹一下128MB內存的末尾,從0x07ff0000 到0x07ff2fff的物理地址範圍中存有加電自測(POST)階段由BIOS寫入的系統硬件設備信息;在初始化階段,內核把這些信息拷貝到一個合適的內核數據結構中,然後認爲這些頁框是可用的。相反,從0x07ff3000到0x07ffffff的物理地址範圍被映射到硬件設備的ROM芯片。從0xffff0000開始的物理地址範圍標記爲保留,因爲它由硬件映射到了BIOS的ROM芯片。注意BIOS也許並不提供一些物理地址範圍的信息(在上述圖中,範圍是0x000a0000到 0x000effff)。爲安全可靠起見,Linux假定這樣的範圍是不可用的。

雖然,我們看到第一個MB裏,BIOS並沒有用完,但是爲了避免把內核裝入一組不連續的頁框裏,影響性能,Linux便跳過第1MB的RAM,之間從第2個MB開始加載。其實一般來說,對於兩個MB,也就是512個頁框,對初始化時的內核代碼及一些靜態數據,已經足夠了。

內核可能不會見到BIOS報告的所有物理內存:例如,如果未使用PAE支持來編譯,即使有更大的物理內存可供使用,內核也只能尋址4GB大小的RAM。setup_memory()函數在machine_specific_memory_setup()執行後被調用:它分析物理內存區域表並初始化一些變量來描述內核的物理內存佈局,這些變量如下表所示:

 

變量名稱

說明

num_physpages

最高可用頁框的頁框號

totalram_pages

可用頁框的總數量

min_low_pfn

RAM 中在內核映像後第一個可用頁框的頁框號

max_pfn

最後一個可用頁框的頁框號

max_low_pfn

被內核直接映射的最後一個頁框的頁框號(低地址內存)

totalhigh_pages

內核非直接映射的頁框的總數(高地址內存)

highstart_pfn

內核非直接映射的第一個頁框的頁框號

highend_pfn

內核非直接映射的最後一個頁框的頁框號



下圖顯示Linux怎樣填充前3MB的RAM。
內存佈局
我們看到圖中可用的頁框,是內存的其餘部分,我們稱爲動態內存,這不僅是進程所需的寶貴資源,也是內核本身所需的寶貴資源。實際上,整個系統的性能取決於如何有效地管理動態內存。因此,現在所有多任務操作系統都在盡力優化對動態內存的使用,也就是儘可能做到當需要是分配,不需要時釋放。

後面的博文中,我們將重點討論內核如何給自己分配動態內存。主要包括頁框管理、高端內存映射、夥伴系統算法、slab分配器、內存池、非連續內存區管理。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章