uclinux啟動過程詳細(xì)分析
存儲了可用物理內(nèi)存起始地址的變量memory_start的初始化是通過一個ld腳本中定義的變量_end進(jìn)行的。ld腳本是用來控制GNU ld連接器在連接內(nèi)核各個目標(biāo)文件部分的時候的配置動作,比如這樣一個腳本:
SECTION
{
。=0x10000;
.text:{*(.text)}
。=0x8000000;
.data:{*(.data)}
.bss :{*(.bss)}
}
用來配置ld連接目標(biāo)文件的時候?qū)⑺械哪繕?biāo)文件中的存儲程序正文的.text段(section)連接到一起,并且映射到輸出文件的地址0x10000處,將所有目標(biāo)文件中已初始化的數(shù)據(jù).data段連接到一起并放置到輸出可執(zhí)行文件的0x8000000地址處,而所有目標(biāo)文件中還未初始化的數(shù)據(jù)段.bss連接起來后影射到輸出文件中緊跟在.data段之后的位置。
這個ld配置腳本文件對每個平臺都是不同的。如為MICETEK上所使用的uClinux版本使用的ld配置文件為arch/armnomm/vmLinux.lds??梢酝ㄟ^修改某個平臺上的ld腳本配置文件中的_end變量來達(dá)到配置其可用物理內(nèi)存起始地址的目的。
setup_arch()在完成對memory_start變量的初始化之后,通過某些特定手段檢測不同類型的內(nèi)存分布情況。比如為檢測某段地址范圍是否為RAM的方法是通過將某個地址的數(shù)據(jù)讀出來,將它加1后寫回內(nèi)存地址中,然后再讀出來和原始數(shù)據(jù)比較看看其值是否成功增加了1,這樣反復(fù)操作兩次,最后將數(shù)據(jù)恢復(fù)。如果是可讀可寫的RAM,那么這個測試的結(jié)果就是每次比較都是成功的,否則就不能將這個地址當(dāng)作RAM。
在setup_arch()中還可能根據(jù)所用平臺進(jìn)行對flash memory和ROM的測試。在這些平臺相關(guān)的工作完成之后,setup_arch()將對系統(tǒng)運行的第一個進(jìn)程init_task的mm_struct結(jié)構(gòu)中描述地址空間分布的變量start_code,end_code,end_data和brk進(jìn)行初始化,start_code為0,其他三個數(shù)值分別為來自于ld腳本配置文件中定義的相關(guān)變量_etext、_edata和_end。
此后setup_arch()將根據(jù)Linux中為系統(tǒng)中的第一塊rom/flash memory card所分配的固定的主/從設(shè)備號(可以從Document/devices.txt中得到)來創(chuàng)建根文件系統(tǒng)的設(shè)備號,并存儲在后來將要用到的全局變量ROOT_DEV中。
setup_arch()最后完成對系統(tǒng)啟動參數(shù)的保存。
在調(diào)用setup_arch()返回之后,start_kernel()中得到了系統(tǒng)可用物理內(nèi)存的起始和結(jié)束地址,以及命令啟動時的命令行參數(shù)。
(2) paging_init()
在Linux中,paging_init()的一項主要功能是建立頁目錄和頁表,而且將Linux移植到不同平臺的過程中非常重要的一個步驟就是修改這個函數(shù)來適應(yīng)新的硬件平臺的虛擬內(nèi)存體系。但是由于在uClinux中不再使用虛擬內(nèi)存機(jī)制,也就不再需要維護(hù)頁目錄和頁表數(shù)據(jù)結(jié)構(gòu)了,所以paging_init()在這里只是為系統(tǒng)啟動的時候保留一部分特殊用途的內(nèi)存區(qū)間。它返回后,從可以使用的內(nèi)存空間開始,依次是如下的數(shù)據(jù)結(jié)構(gòu):
empty_bad_page_table 占用1頁(4KB)
empty_bad_page 占用1頁(4KB)
empty_zero_page 占用1頁,并初始化為全0
mem_map
bitmap
paging_init()函數(shù)在返回前通過調(diào)用free_area_init(start_mem,end_mem)進(jìn)行建立buddy system的映射位圖關(guān)系,以及建立空閑物理頁面鏈表的操作。
(3)free_area_init()
這個函數(shù)用于建立管理物理頁幀的數(shù)據(jù)結(jié)構(gòu)mem_map,有多少物理頁幀就有多少mem_map_t類型的結(jié)構(gòu)體與之相對應(yīng)。每個頁面的mem_map_t結(jié)構(gòu)中的flags被標(biāo)明為PG_DMA和PG_reserved,并且頁幀號被賦給相應(yīng)的數(shù)值。同時建立了管理空閑頁面的bitmap映射表,并且所有的位都被清零。
(3) mem_init()
mem_init()函數(shù)遍歷整個可用物理內(nèi)存地址空間,將每個頁面相對應(yīng)的struct page結(jié)構(gòu)中flags的PG_reserved 標(biāo)志位清除,標(biāo)志用戶個數(shù)的count計數(shù)器置1,并同時統(tǒng)計可用物理頁面數(shù)量,然后打印系統(tǒng)的各個內(nèi)存參數(shù),如可用RAM和ROM的大小、內(nèi)核代碼段和數(shù)據(jù)段大小等。
======================================================
摘 要:本文采用三星公司的S3C44B0微處理器,對uClinux操作系統(tǒng)內(nèi)核的引導(dǎo)過程進(jìn)行了剖析。
關(guān)鍵字:S3C44B0X;uClinux;嵌入式系統(tǒng);內(nèi)核引導(dǎo)
1 前言
伴隨著微電子的發(fā)展,用于嵌入式設(shè)備的處理器速度越來越快,功能也越來越強大。三星公司生產(chǎn)的S3C44B0微處理器,采用的是ARM7TDMI內(nèi)核。該內(nèi)核因為有著功耗小、成本低等特點,因此非常適合作為移動手持終端的處理器核心。Linux操作系統(tǒng)因為它的開放性,使得它不斷的被應(yīng)用到各個領(lǐng)域。在嵌入式領(lǐng)域同樣也出現(xiàn)了各種各樣的Linux變體,最常用的是uClinux。也正是因為uClinux操作系統(tǒng)支持不帶MMU單元的ARM處理器,因此該系統(tǒng)可以對S3C44B0微處理器有很好的支持。
在嵌入式系統(tǒng)開發(fā)中,第一個部分便是系統(tǒng)的引導(dǎo)。而系統(tǒng)的引導(dǎo)過程是通過BootLoader來完成的。BootLoader程序是與硬件緊密相關(guān)的一段代碼,而且編寫的時候比較復(fù)雜,它主要的功能是初始化微處理器以及周邊的硬件資源,并且引導(dǎo)操作系統(tǒng)的啟動。下面我將以S3C44B0微處理器來作為例子,對uClinux操作系統(tǒng)內(nèi)核的引導(dǎo)過程進(jìn)行一個剖析。
2 BootLoader程序概念
簡單的說Boot Lodaer就是在操作系統(tǒng)內(nèi)核運行之前運行的一段小程序,通過這段小程序,可以初始化硬件設(shè)備、建立系統(tǒng)的內(nèi)存空間映射圖,從而將系統(tǒng)的軟硬件環(huán)境設(shè)置成一個適合的狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好正確的環(huán)境。最終,BootLoader把操作系統(tǒng)內(nèi)核映象加載到RAM中,并將系統(tǒng)控制權(quán)傳遞給它。
2.1 典型的BootLoader程序框架
操作系統(tǒng)角度來說,Boot Loader的總目標(biāo)就是正確的調(diào)用內(nèi)核來執(zhí)行。
由于Boot Loader的實現(xiàn)依賴于CPU的體系結(jié)構(gòu),因此大多數(shù)Boot Loader都分為Stage1和Stage2兩大部分。依賴于CPU體系結(jié)構(gòu)的代碼,例如設(shè)備初始化代碼等,通常都放在Stage1中,而且通常都用匯編語言來實現(xiàn),以達(dá)到短小精悍的目的。而Stage2通常用C語言來實現(xiàn),這樣可以實現(xiàn)更加復(fù)雜的功能,而且代碼會具有更好的可讀性和可移植性。
Boot Loader的Stage1通常包括如下步驟:
1) 硬件設(shè)備初始化
評論