記憶體初始化過程

2021-05-23 02:25:40 字數 2194 閱讀 6201

1, 物理記憶體資訊的獲取

0x15中斷,功能號:e820h, e801h, e88h

見檔案:linux/arch/i386/boot/setup.s

執行完上面的**後,記憶體資訊被分為多條資訊放在e820map位置處,每個資訊條目長20位元組,包含乙個記憶體區間的資訊,條目數放在e820nr處。即實際上條目資訊被放到了empty_zero_page的偏移為e820map(即0x2d0)處,條目數被放到偏移為e820nr(即0x1e8)處。

2, start_kernel()->setup_arch()

setup_arch()中與記憶體有關的主要工作為初始化一些與物理頁面管理有關的資料結構,如描述整個物理記憶體資訊的e820變數,描述記憶體結點的pg_data_t物件,啟動時低端記憶體分配器bootmem_data物件,以及最終物理頁面的主要管理機構zone-buddy system。

setup_memory_region()主要是把第一步中獲得的記憶體資訊從empty_zero_page中拷到e820變數中來。因為記憶體資訊報告的區段有可能是凌亂的,比如重疊,順序顛倒等,所以setup_memory_region()首先呼叫sanitize_e820_map()原地將資訊進行整理,再呼叫copy_e820_map()將資訊拷貝到e820變數中。如果資訊有誤,linux保守的估計兩個記憶體區段來初始化e820變數。

setup_memory()主要完成高低端記憶體的劃分,啟動時低端記憶體分配器bootmem_data物件的初始化,並將e820中低端記憶體匯入此分配器進行管理。

setup_memory()呼叫find_max_low_pfn()進行高低端記憶體的劃分;所謂低端記憶體是指核心直接對映的記憶體,高階記憶體指核心不直接對映的記憶體。因為linux將3gb~4gb範圍的1gb線性位址用於核心空間,而4gb頂端的128mb線性位址空間用於vmalloc以及fixed-address特殊對映,還剩下1gb-128mb=896mb的線性位址可用於直接對映物理記憶體,所以在物理記憶體充足的情況下,至少有896mb物理記憶體是直接對映到核心空間的,稱為低端記憶體;大於896mb的不能直接對映到核心空間(因為線性位址不夠)稱為高階記憶體。顯然896為低端記憶體的最大值提供了乙個限定。然而,高低端記憶體的劃分還必須可以由人為介入(由啟動引數控制),尤其是當物理記憶體小於896mb的時候,在這種情況下,沒有理由規定核心必須將所有的記憶體都直接對映到3gb~4gb中,所以可以通過highmem_pages變數來指定將多少記憶體「不用於」直接對映,即將多少記憶體用於高階記憶體。呼叫完find_max_low_pfn()以後,以下變數被設定:

max_low_pfn: 低端記憶體的終止頁框號

max_pfn:         記憶體的終止頁框號,即實際使用的物理頁框數。它可能會小於真正存在的物理頁框總數(e820中的最大頁框數), 例如大於896mb的物理記憶體數多於使用者指定的高階記憶體數時,以使用者指定的為準,這樣實際上有很多頁框不會被使用。

接著setup_memory()設定高階記憶體界限。highstart_pfn = max_low_pfn; highend_pfn = max_pfn; 顯然[max_low_pfn, max_pfn)為高階記憶體。然後init_bootmem()初始化啟動時記憶體分配器,用於在夥伴系統及slab分配器建立之前分配記憶體。分配器初始化後用register_bootmem_low_pages()將所有的低端記憶體頁框納入其管理之下。至此就可以使用此分配器將某些特殊作用的記憶體頁面設定為保留(即永久性占有),或是使用其分配記憶體等等。

register_memory()主要是給記憶體註冊匯流排位址空間。重點關注對匯流排位址空間的管理,兩棵resoure樹(iomem_resource/ioport_resource)。

3, start_kernel()->mem_init()

執行到此,夥伴系統管理資料結構已初始化完畢,接著就只需要往裡面放入物理頁面了。mem_init()主要就做這件事。其呼叫free_pages_init()一方面把啟動時分配器中空閒的低端記憶體頁面放入夥伴系統,另一方面直接把[highstart_pfn, highend_pfn)中的高階記憶體頁面放入夥伴系統。

物理頁面到了zone-buddy system中,往後就簡單多了。 

記憶體初始化

電容的分類 dram 基本原件是電容,需要定時重新整理,儲存速度較慢 dram又分為 sram 同步動態隨機儲存器 synchronous dynamic random access memory ddr 雙倍速率同步動態隨機儲存器 double data rate sdram ddr2 在 ddr...

類初始化和例項初始化過程

類初始化過程 乙個類要建立例項需要先載入並初始化該類 main方法所在的類需要先載入和初始化 乙個子類要初始化需要先初始化父類 乙個類初始化就是執行 方法 由靜態類變數賦值 和靜態 塊組成 靜態類變數賦值 和靜態 塊從上往下執行 方法只執行一次 例項初始化過程 例項初始化就是執行 方法 方法可能過載...

Struts初始化過程

sturts初始化過程取決於在web.xml檔案中配置的初始化引數,servlet容器在首次啟動或servlet的第一次請求到達時載入struts actionservlet。在這兩種情況下,要保證init 方法被呼叫,並且必須在servlet處理任何請求之前完成。當init 被呼叫時,struts...