第4章 嵌入式Linux的構(gòu)建(2012-10-9)_第1頁(yè)
第4章 嵌入式Linux的構(gòu)建(2012-10-9)_第2頁(yè)
第4章 嵌入式Linux的構(gòu)建(2012-10-9)_第3頁(yè)
第4章 嵌入式Linux的構(gòu)建(2012-10-9)_第4頁(yè)
第4章 嵌入式Linux的構(gòu)建(2012-10-9)_第5頁(yè)
已閱讀5頁(yè),還剩99頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第4章

嵌入式Linux的構(gòu)建4.1嵌入式BootLoader技術(shù)4.2嵌入式Linux根文件系統(tǒng)構(gòu)建4.3

Linux內(nèi)核及啟動(dòng)過(guò)程4.4基于ARM目標(biāo)板的Linux系統(tǒng)及應(yīng)用程序的燒寫(xiě)4.1嵌入式BootLoader技術(shù)4.1.1

Bootloader的概念

簡(jiǎn)單地說(shuō),BootLoader就是在操作系統(tǒng)內(nèi)核運(yùn)行之前運(yùn)行的一段小程序。通過(guò)這段小程序,可以初始化硬件設(shè)備、建立內(nèi)存空間的映射圖,從而將系統(tǒng)的軟硬件環(huán)境帶到一個(gè)合適的狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好正確的環(huán)境。

通常,BootLoader是嚴(yán)重地依賴(lài)于硬件而實(shí)現(xiàn)的,特別是在嵌入式系統(tǒng)。因此,在嵌入式系統(tǒng)里建立一個(gè)通用的BootLoader幾乎是不可能的。盡管如此,仍然可以對(duì)BootLoader歸納出一些通用的概念來(lái),以指導(dǎo)用戶(hù)特定的BootLoader設(shè)計(jì)與實(shí)現(xiàn)。

每種不同的CPU體系結(jié)構(gòu)都有不同的BootLoader。有些BootLoader也支持多種體系結(jié)構(gòu)的CPU,比如U-Boot就同時(shí)支持ARM體系結(jié)構(gòu)和MIPS體系結(jié)構(gòu)。除了依賴(lài)于CPU的體系結(jié)構(gòu)外,BootLoader實(shí)際上也依賴(lài)于具體的嵌入式板級(jí)設(shè)備的配置。這也就是說(shuō),對(duì)于兩塊不同的嵌入式板而言,即使它們是基于同一種CPU而構(gòu)建的,要想讓運(yùn)行在一塊板子上的BootLoader程序也能運(yùn)行在另一塊板子上,通常也都需要修改BootLoader的源程序。1.BootLoader所支持的CPU和嵌入式開(kāi)發(fā)板

2.BootLoader的安裝媒介(InstallationMedium)系統(tǒng)加電或復(fù)位后,所有的CPU通常都從某個(gè)由CPU制造商預(yù)先安排的地址上取指令。比如,基于ARM920T核的CPU在復(fù)位時(shí)通常都從地址0x00000000取它的第一條指令。而基于CPU構(gòu)建的嵌入式系統(tǒng)通常都有某種類(lèi)型的固態(tài)存儲(chǔ)設(shè)備(比如:ROM、EEPROM或FLASH等)被映射到這個(gè)預(yù)先安排的地址上。因此在系統(tǒng)加電后,CPU將首先執(zhí)行BootLoader程序。

圖4.1所示的就是一個(gè)同時(shí)裝有BootLoader、內(nèi)核的啟動(dòng)參數(shù)、內(nèi)核映像和根文件系統(tǒng)映像的固態(tài)存儲(chǔ)設(shè)備的典型空間分配結(jié)構(gòu)圖。

圖4.1固態(tài)存儲(chǔ)設(shè)備的典型空間分配結(jié)構(gòu)

3.用來(lái)控制BootLoader的設(shè)備或機(jī)制

主機(jī)和目標(biāo)機(jī)之間一般通過(guò)串口建立連接,BootLoader軟件在執(zhí)行時(shí)通常會(huì)通過(guò)串口來(lái)進(jìn)行I/O,比如:輸出打印信息到串口,從串口讀取用戶(hù)控制字符等。

4.BootLoader的啟動(dòng)過(guò)程是單階段(SingleStage)還是多階段(Multi-Stage)通常多階段的BootLoader能提供更為復(fù)雜的功能,以及更好的可移植性。從固態(tài)存儲(chǔ)設(shè)備上啟動(dòng)的BootLoader大多都是2階段的啟動(dòng)過(guò)程,也即啟動(dòng)過(guò)程可以分為stage1和stage2兩部分。而至于在stage1和stage2具體完成哪些任務(wù)將在下面討論。

5.BootLoader的操作模式(OperationMode)

①啟動(dòng)加載(Bootloading)模式:這種模式也稱(chēng)為"自主"(Autonomous)模式。也即BootLoader從目標(biāo)機(jī)上的某個(gè)固態(tài)存儲(chǔ)設(shè)備上將操作系統(tǒng)加載到RAM中運(yùn)行,整個(gè)過(guò)程并沒(méi)有用戶(hù)的介入。這種模式是BootLoader的正常工作模式,因此在嵌入式產(chǎn)品發(fā)布的時(shí)侯,BootLoader顯然必須工作在這種模式下。②下載(Downloading)模式:在這種模式下,目標(biāo)機(jī)上的BootLoader將通過(guò)串口連接或網(wǎng)絡(luò)連接等通信手段從主機(jī)(Host)下載文件,比如:下載內(nèi)核映像和根文件系統(tǒng)映像等。從主機(jī)下載的文件通常首先被BootLoader保存到目標(biāo)機(jī)的RAM中,然后再被BootLoader寫(xiě)到目標(biāo)機(jī)上的FLASH類(lèi)固態(tài)存儲(chǔ)設(shè)備中。BootLoader的這種模式通常在第一次安裝內(nèi)核與根文件系統(tǒng)時(shí)被使用;此外,以后的系統(tǒng)更新也會(huì)使用BootLoader的這種工作模式。工作于這種模式下的BootLoader通常都會(huì)向它的終端用戶(hù)提供一個(gè)簡(jiǎn)單的命令行接口。6.BootLoader與主機(jī)之間進(jìn)行文件傳輸所用的通信設(shè)備及協(xié)議一般情況,目標(biāo)機(jī)上的BootLoader通過(guò)串口與主機(jī)之間進(jìn)行文件傳輸,傳輸協(xié)議通常是xmodem/ymodem/zmodem協(xié)議中的一種。但是,串口傳輸?shù)乃俣仁怯邢薜?,因此通過(guò)以太網(wǎng)連接并借助TFTP協(xié)議來(lái)下載文件是個(gè)更好的選擇。

還必須考慮主機(jī)方所用的軟件。比如,在通過(guò)以太網(wǎng)連接和TFTP協(xié)議來(lái)下載文件時(shí),主機(jī)方必須有一個(gè)軟件用來(lái)的提供TFTP服務(wù)。

4.1.2Bootloader引導(dǎo)程序Bootloader引導(dǎo)程序是嵌入式開(kāi)發(fā)很重要的組成部分。它是嵌入式系統(tǒng)上電后執(zhí)行的第一個(gè)程序,并由它最終將操作系統(tǒng)啟動(dòng)起來(lái)并將控制權(quán)交給操作系統(tǒng)。Bootloader引導(dǎo)程序最基本的功能是對(duì)硬件系統(tǒng)的初始化和內(nèi)核啟動(dòng)參數(shù)設(shè)置并啟動(dòng)內(nèi)核。Bootloader的主要功能有:(1)初始化CPU的主頻、SDRAM、中斷、串口等硬件;(2)啟動(dòng)Linux內(nèi)核并提供一個(gè)RAMDISK;(3)通過(guò)串口下載內(nèi)核或RAMDISK到目標(biāo)板上;(4)將修改過(guò)的內(nèi)核或RAMDISK寫(xiě)入到Flash內(nèi);(5)為用戶(hù)提供一個(gè)命令接口?!馚ootloader的stage1stage1是Bootloader一開(kāi)始就執(zhí)行的操作,其目的是為了stage2的執(zhí)行以及隨后的內(nèi)核的執(zhí)行,設(shè)置好一些基本的硬件環(huán)境。包括以下步驟:①屏蔽所有的中斷。為中斷提供服務(wù)的通常是操作系統(tǒng),因此在執(zhí)行Bootloader的過(guò)程中可以不響應(yīng)任何中斷。中斷屏蔽通過(guò)寫(xiě)CPU的中斷屏蔽寄存器來(lái)完成。②設(shè)置CPU的時(shí)鐘頻率和速度。③初始化RAM設(shè)置系統(tǒng)內(nèi)存控制器的功能寄存器和各內(nèi)存庫(kù)控制寄存器等。④為加載stage2準(zhǔn)備RAM空間。⑤拷貝stage2到RAM中。⑥跳轉(zhuǎn)到stage2的入口點(diǎn)?!馚ootloader的stage2

stage2的主要的功能是通過(guò)串口下載Linux內(nèi)核到目標(biāo)板上。包括以下幾個(gè)步驟:①初始化本階段要使用到的硬件設(shè)備。通常包括:初始化至少一個(gè)串口,以便和終端用戶(hù)進(jìn)行I/O輸出信息;初始化計(jì)時(shí)器等。②檢測(cè)系統(tǒng)的內(nèi)存映射。所謂內(nèi)存映射就是指在整個(gè)4GB物理地址空間中有哪些地址范圍被分配用來(lái)尋址系統(tǒng)的RAM單元。③加載內(nèi)核映像和根文件系統(tǒng)從Flash讀入到Rom中。包括兩個(gè)方面:第一方面是內(nèi)核映像所占用的內(nèi)存范圍;第二方面是根文件系統(tǒng)所占用的內(nèi)存范圍。在規(guī)劃內(nèi)存占用布局時(shí),主要考慮基地址和映像的大小兩個(gè)方面。④設(shè)置內(nèi)核的啟動(dòng)參數(shù)。⑤調(diào)用內(nèi)核。Bootloader調(diào)用Linux內(nèi)核的方法是直接跳轉(zhuǎn)到內(nèi)核的第一條指令處。2.BootLoader代碼分析

下面對(duì)引導(dǎo)程序2410INIT.S進(jìn)行分析,以加深對(duì)BootLoader的理解。在第一階段完成依賴(lài)于體系結(jié)構(gòu)硬件初始化的代碼,包括禁止看門(mén)狗、禁止中斷、初始化各控制寄存器拷貝自身到RAM等。IMPORTMain AREAInit,CODE,READONLY ENTRY …… b ResetHandler ……ResetHandler ldr r0,=WTCON ldr r1,=0x0 str r1,[r0] ldr r0,=INTMSK ldr r1,=0xffffffff str r1,[r0] ldr r0,=INTSUBMSK ldr r1,=0x7ff str r1,[r0] …… ldr r0,=LOCKTIME ldr r1,=0xffffff str r1,[r0] …… ldr r0,=SMRDATA ldr r1,=BWSCON add r2,r0,#52 ldr r3,[r0],#4 str r3,[r1],#4 cmp r2,r0 bne %B0 ……第二階段通常用C語(yǔ)言實(shí)現(xiàn),包括內(nèi)存管理單元初始化、時(shí)鐘設(shè)置、端口設(shè)置和串口初始化等。voidIsr_Init(void){rINTMOD=0x0;//工作在IRQ模式rINTMSK=BIT_ALLMSK;//屏蔽中斷rINTSUBMSK=BIT_SUB_ALLMSK;//屏蔽子中斷}voidMain(void){MMU_Init(); //MMU初始化ChangeClockDivider(1,1);//設(shè)置時(shí)鐘除法器->1:2:4ChangeMPllValue(0xa1,0x3,0x1);//時(shí)鐘值FCLK=202.8MHzPort_Init(); Isr_Init();Uart_Init(0,115200);Uart_Select(0);while(1){ …… Uart_Printf("\n\nSMDK2410Board(MCUS3C2410)ExampleProgramVer1.0(20020521)FCLK=%dHz\n\n",FCLK); ……}}

與一般的C語(yǔ)言程序一樣,第二階段程序從Main()函數(shù)開(kāi)始。因?yàn)樗捎玫腟3C2410X處理器內(nèi)含存儲(chǔ)器管理單元MMU,所以首先需要進(jìn)行存儲(chǔ)器管理單元的初始化。緊接著設(shè)置系統(tǒng)工作主時(shí)鐘,若使用USB設(shè)備則USB時(shí)鐘也需要做相應(yīng)初始化。其次對(duì)端口工作狀態(tài)進(jìn)行設(shè)定。然后設(shè)定處理器工作模式,以及中斷控制。最后初始化串口,與宿主機(jī)建立聯(lián)系,以利于顯示調(diào)試信息。啟動(dòng)成功后,可以執(zhí)行主程序。4.1.3VIVI簡(jiǎn)介VIVI是韓國(guó)Mizi公司開(kāi)發(fā)的BootLoader,可用于ARM9處理器的引導(dǎo)。VIVI利用串行通信為用戶(hù)提供接口。為連接VIVI,首先利用串口電纜連接宿主機(jī)和目標(biāo)板,然后在主機(jī)上運(yùn)行串口通信程序,并在目標(biāo)板上正確設(shè)置VIVI以支持串口。在宿主機(jī)進(jìn)入超級(jí)終端后,打開(kāi)目標(biāo)板電源或按目標(biāo)板復(fù)位鍵,就可以由串口通信程序顯示提示信息,提示信息的最后一行如下所示:PressReturntostarttheLINUXnow,anyotherkeyforvivi.VIVI也有前面說(shuō)過(guò)的兩種工作模式,啟動(dòng)模式可以在一段時(shí)間后自行啟動(dòng)Linux內(nèi)核,這是VIVI的默認(rèn)方式。出現(xiàn)上述信息后,如果按除回車(chē)鍵外的任意鍵,即可進(jìn)入下載模式,出現(xiàn)“vivi>”提示符。有如下作用:●把內(nèi)核(kernel)從flash復(fù)制到RAM,然后啟動(dòng);●初始化硬件;●下載程序并寫(xiě)入flash(通常由串口或者網(wǎng)口先把內(nèi)核下載到RAM中,然后寫(xiě)入flash);●檢測(cè)目標(biāo)板(bootloader會(huì)有一些簡(jiǎn)單的代碼用以測(cè)試目標(biāo)板硬件的好壞)。在下載模式下,VIVI為用戶(hù)提供了一個(gè)命令行接口,通過(guò)該接口可以使用VIVI提供的一些命令。

1.VIVI的命令

(1)load命令

將二進(jìn)制文件載入到Flash或者RAM,命令格式:load<media_type>[<partname>|<addr><size>]<x|y|z>其中命令行參數(shù)<media_type>描述裝載位置,有flash和ram兩種選項(xiàng);參數(shù)[<partname>]或[<addr><size>]描述裝載的地址,如果有提前定義的mtd分區(qū)信息,可以只輸入分區(qū)名稱(chēng),否則需要指定地址和大?。粎?shù)<x|y|z>確定文件的傳輸協(xié)議,常采用的選項(xiàng)“x”用來(lái)指定采用xmodem協(xié)議。

例如:vivi>loadflashkernelx,裝載壓縮映像文件zImage到flash存儲(chǔ)器中,地址是kernel分區(qū),采用xmodem傳輸協(xié)議。也可以指定地址和大小,例如:vivi>loadflash0x800000xc0000x。(2)part命令操作MTD分區(qū)信息,比如,顯示、增加、刪除、復(fù)位、保存MTD分區(qū)等?!駊artshow:顯示mtd分區(qū)信息?!駊artadd<name><offset><size><flag>:增加新的mtd分區(qū),其中<name>為新mtd分區(qū)名稱(chēng),<offset>是mtd器件的偏移,<size>表示mtd分區(qū)的大小,<flag>表示分區(qū)類(lèi)型,可選項(xiàng)有JFFS2、LOCKED和BONFS。●partdel<partname>:刪除一個(gè)mtd分區(qū)?!駊artreset:恢復(fù)mtd分區(qū)為默認(rèn)值?!駊artsave:在flash中永久保存參數(shù)值和分區(qū)信息。(3)param命令用來(lái)設(shè)置或者察看參數(shù)。例如:改變“l(fā)inuxcommandline”,使用vivi>paramsetlinux_cmd_line"youwish."。也可以改變引導(dǎo)程序啟動(dòng)的時(shí)間,使用vivi>paramsetboot_delay100000實(shí)現(xiàn)。

(4)boot命令

用來(lái)引導(dǎo)存儲(chǔ)在flash存儲(chǔ)器或ram中的linux內(nèi)核。命令格式:boot<media_type>[<partname>|<addr><size>]參數(shù)<media_type>設(shè)定存儲(chǔ)linux內(nèi)核映像的位置,可選項(xiàng)有ram、nor和smc。

參數(shù)[<partname>]或[<addr><size>]描述存儲(chǔ)內(nèi)核的地址,如果有提前定義的mtd分區(qū)信息,可以只輸入分區(qū)名稱(chēng),否則需要指定地址和大小。例如:vivi>bootnor0x80000表示從flash存儲(chǔ)器中讀出linux內(nèi)核,偏移是0x80000。

(5)flash命令

存儲(chǔ)器管理命令,例如:flasherase[<partname>|<offset><size>],表示擦除flash存儲(chǔ)器。2.VIVI的目錄樹(shù)(1)arch:此目錄包括了所有VIVI支持的目標(biāo)板的子目錄,本書(shū)附帶的代碼中只包含S3C2410X。(2)Documentation:存放了許多文檔,其中包括VIVI的使用指南。(3)drivers:其中包括了引導(dǎo)內(nèi)核所需的MTD設(shè)備和串口驅(qū)動(dòng)程序。MTD目錄下分maps、nand和nor三個(gè)目錄,實(shí)現(xiàn)對(duì)NandFlash和NorFlash的讀寫(xiě)控制。Serial目錄下的文件實(shí)現(xiàn)對(duì)串口的控制,并支持xmodem和ymodem協(xié)議。(4)include:頭文件的公共目錄,其中的S3C2410.h定義了處理器的一些寄存器,以及NANDFlash的一些寄存器等。Platform/smdk2410.h定義了與目標(biāo)板相關(guān)的資源配置參數(shù),修改波特率、引導(dǎo)參數(shù)和物理內(nèi)存映射等參數(shù)即可配置目標(biāo)板。(5)init:此目錄只有main.c和version.c兩個(gè)文件。與普通的C程序一樣,VIVI將從main函數(shù)開(kāi)始執(zhí)行。(6)lib:一些平臺(tái)公共的接口代碼,比如,time.c里的udelay()和mdelay()。(7)scripts:此目錄存放了配置所需的腳本文件,如Menuconfig和Configure文件,以方便對(duì)VIVI的配置。

VIVI的運(yùn)行也可以分為兩個(gè)階段。在第一階段完成含有依賴(lài)于CPU體系結(jié)構(gòu)硬件初始化的代碼,利用匯編語(yǔ)言完成。第二階段是用C語(yǔ)言完成的。即在VIVI中以head.S作為第一階段,main()作為第二階段。在跳轉(zhuǎn)進(jìn)main()函數(shù)之前,利用匯編語(yǔ)言編寫(xiě)了一段trampoline程序作為階段2可執(zhí)行鏡像的執(zhí)行入口點(diǎn)。之后可以在trampoline中用處理器的跳轉(zhuǎn)指令進(jìn)入main()函數(shù)中去執(zhí)行。當(dāng)main()函數(shù)返回時(shí),CPU就進(jìn)行復(fù)位。VIVI的程序代碼請(qǐng)參考本書(shū)提供的光盤(pán):\2410s\exp\bootloader\vivi\arch\s3c2410的文件夾中的head.S程序,VIVI的下載燒寫(xiě)在4.7節(jié)詳細(xì)介紹。3.配置和編譯vivi

如果vivi的源代碼已根據(jù)開(kāi)發(fā)板作了相應(yīng)改動(dòng),則需要對(duì)源代碼進(jìn)行配置和編譯,以生成燒入flash的vivi二進(jìn)制映象文件。

由于vivi要用到kernel的一些頭文件,所以需要kernel的源代碼,所以先要把linux的kernel準(zhǔn)備好。將vivi和kernel都解到相應(yīng)目錄下(例如將光盤(pán)提供的vivi源代碼解壓到/home/xiongmh目錄下,光盤(pán)提供的Linuxkernel源碼kernel-h2410eb.041024.tar.gz也解壓到/home/xiongmh目錄下,解壓后的文件名為kerne-h2410eb)。然后需修改/vivi/Makefile文件中的一些變量設(shè)置:

LINUX_INCLUDE_DIR=/kernel/include/修改為:

LINUX_INCLUDE_DIR=/home/xiongmh/kerne-h2410eb/include/?CROSS_COMPILE=/usr/local/arm/2.95.3/bin/arm-linux-修改為:

CROSS_COMPILE=/usr/local/arm/2.95.3/bin/arm-linux-ARM_GCC_LIBS=/usr/local/arm/2.95.3/lib/gcc-lib/arm-linux/2.95.3進(jìn)入/vivi目錄執(zhí)行makedistclean。(目的是確保編譯的有效性,在編譯之前將vivi里所有的“*.o”和“*.o.flag”文件刪掉)

進(jìn)入/vivi目錄里,輸入makemenuconfig,開(kāi)始選擇配置。也可用Load裝入一個(gè)寫(xiě)好的配置文件。注意,選Exit退出時(shí)一定要選“Yes”保存配置。再輸入make正式開(kāi)始編譯直至完成。如果不報(bào)錯(cuò),配置和編譯得到的“vivi”在/vivi的文件夾中。這個(gè)就是后面要燒寫(xiě)到flash中的bootloader。4.1.4vivi代碼分析vivi的運(yùn)行也可以分為兩個(gè)階段:

1.vivi的第一階段完成含依賴(lài)于CPU的體系結(jié)構(gòu)硬件初始化的代碼,包括禁止中斷、初始化串口、復(fù)制自身到RAM等。相關(guān)代碼集中在head.S(\vivi\arch\s3c2410目錄下):

Head.S:

#include"config.h"#include"linkage.h"#include"machine.h"@StartofexecutablecodeENTRY(_start)ENTRY(ResetEntryPoint)@@Exceptionvectortable(physicaladdress=0x00000000);異常向量表物理地址@@0x00:Reset;復(fù)位bReset@0x04:Undefinedinstructionexception;未定義的指令異常UndefEntryPoint:bHandleUndef@0x08:Softwareinterruptexception;軟件中斷異常SWIEntryPoint:bHandleSWI@0x0c:PrefetchAbort(InstructionFetchMemoryAbort);內(nèi)存操作異常PrefetchAbortEnteryPoint:bHandlePrefetchAbort@0x10:DataAccessMemoryAbort;數(shù)據(jù)異常DataAbortEntryPoint:bHandleDataAbort@0x14:Notused;未使用NotUsedEntryPoint:bHandleNotUsed@0x18:IRQ(InterruptRequest)exception;慢速中斷處理IRQEntryPoint:bHandleIRQ@0x1c:FIQ(FastInterruptRequest)exception;快速中斷處理FIQEntryPoint:bHandleFIQ@VIVImagics@@0x20:magicnumbersowecanverifythatweonlyput.long0@0x24:.long0@0x28:wherethisviviwaslinked,sowecanputitinmemoryintherightplace.long_start@0x2C:thiscontainstheplatform,cpuandmachineid.longARCHITECTURE_MAGIC@0x30:vivicapabilities.long0#ifdefCONFIG_PM;vivi考慮不需要使用電源管理@0x34:bSleepRamProc#endif#ifdefCONFIG_TEST@0x38:bhmi#endif@@StartVIVIhead@Reset:@disablewatchdogtimer;禁止看門(mén)狗計(jì)時(shí)器movr1,#0x53000000;WTCON寄存器地址是0x53000000,清0movr2,#0x0strr2,[r1]#ifdefCONFIG_S3C2410_MPORT3;不符合條件,跳到下面的關(guān)中斷/****在/vivi/include/autoconf.h中#undefCONFIG_S3C2410_MPORT3******/movr1,#0x56000000;GPACON寄存器地址是0x56000000movr2,#0x00000005strr2,[r1,#0x70];配置GPHCON寄存器movr2,#0x00000001strr2,[r1,#0x78];配置GPHUP寄存器movr2,#0x00000001strr2,[r1,#0x74];配置GPHDAT寄存器#endif@disableallinterrupts;禁止全部中斷movr1,#INT_CTL_BASEmovr2,#0xffffffffstrr2,[r1,#oINTMSK];掩碼關(guān)閉所有中斷2.vivi的第二階段vivi的第二階段是從main()函數(shù)開(kāi)始,同一般的C語(yǔ)言程序一樣,該函數(shù)在/init/main.c文件中,總共可以分為8個(gè)步驟。(1)函數(shù)開(kāi)始,通過(guò)putstr(vivi_banner)打印出vivi的版本。Vivi_banner在/init/version.c文件中定義(2)對(duì)開(kāi)發(fā)板進(jìn)行初始化(board_init函數(shù)),board_init是與開(kāi)發(fā)板緊密相關(guān)的,這個(gè)函數(shù)在/arch/s3c2410/smdk.c文件中。開(kāi)發(fā)板初始化主要完成兩個(gè)功能,時(shí)鐘初始化(init_time())和通用IO口設(shè)置(set_gpios())。voidset_gpios(void){GPACON=vGPACON;GPBCON=vGPBCON;GPBUP=vGPBUP;GPCCON=vGPCCON;GPCUP=vGPCUP;GPDCON=vGPDCON;GPDUP=vGPDUP;GPECON=vGPECON;GPEUP=vGPEUP;GPFCON=vGPFCON;GPFUP=vGPFUP;GPGCON=vGPGCON;GPGUP=vGPGUP;GPHCON=vGPHCON;GPHUP=vGPHUP;EXTINT0=vEXTINT0;EXTINT1=vEXTINT1;EXTINT2=vEXTINT2;}其中,GPIO口在smdk2410.h(\vivi\include\platform\目錄下)文件中定義。(3)內(nèi)存映射初始化和內(nèi)存管理單元的初始化工作:

mem_map_init();mmu_init();這兩個(gè)函數(shù)都在/arch/s3c2410/mmu.c文件中。voidmem_map_init(void){#ifdefCONFIG_S3C2410_NAND_BOOTmem_map_nand_boot();#elsemem_map_nor();#endifcache_clean_invalidate();tlb_invalidate();}如果配置vivi時(shí)使用了NAND作為啟動(dòng)設(shè)備,則執(zhí)行mem_map_nand_boot(),否則執(zhí)行mem_map_nor()。這里要注意的是,如果使用NOR啟動(dòng),則必須先把vivi代碼復(fù)制到RAM中。這個(gè)過(guò)程是由copy_vivi_to_ram()函數(shù)來(lái)完成的。代碼如下:

staticvoidcopy_vivi_to_ram(void){putstr_hex("Evacuating1MBofFlashtoDRAMat0x",VIVI_RAM_BASE);memcpy((void*)VIVI_RAM_BASE,(void*)VIVI_ROM_BASE,VIVI_RAM_SIZE);}VIVI_RAM_BASE、VIVI_ROM_BASE、VIVI_RAM_SIZE這些值都可以在smdk2410.h中查到,并且這些值必須根據(jù)自己開(kāi)發(fā)板的RAM實(shí)際大小修改。這也是在移植vivi的過(guò)程中需要注意的一個(gè)地方。mmu_init()函數(shù)中執(zhí)行了arm920_setup函數(shù)。這段代碼是用匯編語(yǔ)言實(shí)現(xiàn)的,針對(duì)arm920t核的處理器。(4)初始化堆棧,heap_init()。(定義在\vivi\lib\heap.c文件中)

intheap_init(void){returnmmalloc_init((unsignedchar*)(HEAP_BASE),HEAP_SIZE);}(5)初始化mtd設(shè)備,mtd_dev_init()。intmtd_init(void){intret;#ifdefCONFIG_MTD_CFIret=cfi_init();#endif#ifdefCONFIG_MTD_SMCret=smc_init();#endif#ifdefCONFIG_S3C2410_AMD_BOOTret=amd_init();#endifif(ret){mymtd=NULL;returnret;}return0;}這幾個(gè)函數(shù)可以在/drivers/mtd/maps/s3c2410_flash.c里找到。(6)初始化私有數(shù)據(jù),init_priv_data()。(定義在\vivi\lib\priv_data\rw.c文件中)

(7)初始化內(nèi)置命令,init_builtin_cmds()。通過(guò)add_command函數(shù),加載vivi內(nèi)置的幾個(gè)命令。(8)啟動(dòng)boot_or_vivi()。啟動(dòng)成功后,將通過(guò)vivi_shell()啟動(dòng)一個(gè)shell(如果配置了CONFIG_SERIAL_TERM),此時(shí)vivi的任務(wù)完成。4.2嵌入式Linux根文件系統(tǒng)構(gòu)建4.2.1Linux文件系統(tǒng)介紹

理論上說(shuō)一個(gè)嵌入式設(shè)備如果內(nèi)核能夠運(yùn)行起來(lái),且不需要運(yùn)行用戶(hù)進(jìn)程的話(huà),是不需要文件系統(tǒng)的,文件系統(tǒng)簡(jiǎn)單的說(shuō)就是一種目錄結(jié)構(gòu),由于linux操作系統(tǒng)的設(shè)備在系統(tǒng)中是以文件的形式存在,將這些文件進(jìn)行分類(lèi)管理以及提供和內(nèi)核交互的接口,就形成一定的目錄結(jié)構(gòu)也就是文件系統(tǒng),文件系統(tǒng)是為用戶(hù)反映系統(tǒng)的一種形式,為用戶(hù)提供一個(gè)檢測(cè)控制系統(tǒng)的接口。

根文件系統(tǒng),我認(rèn)為根文件系統(tǒng)就是一種特殊的文件系統(tǒng),那么根文件系統(tǒng)和普通的文件系統(tǒng)有什么區(qū)別呢?由于根文件系統(tǒng)是內(nèi)核啟動(dòng)時(shí)掛在的第一個(gè)文件系統(tǒng),那么根文件系統(tǒng)就要包括Linux啟動(dòng)時(shí)所必須的目錄和關(guān)鍵性的文件,例如Linux啟動(dòng)時(shí)都需要有init目錄下的相關(guān)文件,在Linux掛載分區(qū)時(shí)Linux一定會(huì)找/etc/fstab這個(gè)掛載文件等,根文件系統(tǒng)中還包括了許多的應(yīng)用程序bin目錄等,任何包括這些Linux系統(tǒng)啟動(dòng)所必須的文件都可以成為根文件系統(tǒng)。圖4.3Linux系統(tǒng)結(jié)構(gòu)Linux支持多種文件系統(tǒng),包括ext2、ext3、vfat、ntfs、iso9660、jffs、romfs和nfs等,為了對(duì)各類(lèi)文件系統(tǒng)進(jìn)行統(tǒng)一管理,Linux引入了虛擬文件系統(tǒng)VFS(VirtualFileSystem),為各類(lèi)文件系統(tǒng)提供一個(gè)統(tǒng)一的操作界面和應(yīng)用編程接口。如4.3所示的Linux系統(tǒng)結(jié)構(gòu)圖。Linux啟動(dòng)時(shí),第一個(gè)必須掛載的是根文件系統(tǒng);若系統(tǒng)不能從指定設(shè)備上掛載根文件系統(tǒng),則系統(tǒng)會(huì)出錯(cuò)而退出啟動(dòng)。之后可以自動(dòng)或手動(dòng)掛載其他的文件系統(tǒng)。因此,一個(gè)系統(tǒng)中可以同時(shí)存在不同的文件系統(tǒng)。不同的文件系統(tǒng)類(lèi)型有不同的特點(diǎn),因而根據(jù)存儲(chǔ)設(shè)備的硬件特性、系統(tǒng)需求等有不同的應(yīng)用場(chǎng)合。在嵌入式Linux應(yīng)用中,主要的存儲(chǔ)設(shè)備為RAM(DRAM,SDRAM)和ROM(常采用FLASH存儲(chǔ)器),常用的基于存儲(chǔ)設(shè)備的文件系統(tǒng)類(lèi)型包括:jffs2,yaffs,cramfs,romfs,ramdisk,ramfs/tmpfs等。4.2.2根文件系統(tǒng)的目錄結(jié)構(gòu)內(nèi)核啟動(dòng)的最后步驟是掛載根文件系統(tǒng),包含:Init進(jìn)程、Shell、文件系統(tǒng)、網(wǎng)絡(luò)系統(tǒng)等等的工具集、系統(tǒng)配置文件和鏈接庫(kù)等。根文件系統(tǒng)是由目錄、Shell、庫(kù)、腳本等組成,根文件系統(tǒng)根目錄下除了可能的標(biāo)準(zhǔn)的系統(tǒng)引導(dǎo)映象/vmlinuz外一般不含任何文件,所有其他文件是在根文件系統(tǒng)的子目錄中。嵌入式根文件系統(tǒng)要包含了一些必須有的目錄,如:/dev、/bin、/usr、/sbin、/lib、/etc、/proc、/sys。下面介紹根文件系統(tǒng)中的主要子目錄。/bin:必要的用戶(hù)命令(二進(jìn)制文件)。*/boot:引導(dǎo)加載程序使用的靜態(tài)文件。/dev:設(shè)備文件及其他特殊文件。/etc:系統(tǒng)配置文件。*/home:用戶(hù)主目錄。/lib:必要的鏈接庫(kù),例如:C鏈接庫(kù)、內(nèi)核模塊。/mnt:臨時(shí)掛載的文件系統(tǒng)的掛載點(diǎn)。*/opt:附加軟件的安裝目錄。proc:提供內(nèi)核和進(jìn)程信息的proc文件系統(tǒng)。*/root:root用戶(hù)主目錄。sbin:必要的系統(tǒng)管理員命令。tmp:臨時(shí)文件目錄。usr:大多數(shù)用戶(hù)使用的應(yīng)用程序和文件目錄。var:監(jiān)控程序和工具程序存放的可變數(shù)據(jù)。注意:“*”目錄在嵌入式Linux上為可選的。(1)/dev目錄在/dev目錄中,包括設(shè)備文件及其他特殊文件,當(dāng)配置內(nèi)核支持設(shè)備文件系統(tǒng)devfs時(shí),此目錄中的設(shè)備節(jié)點(diǎn)由內(nèi)核和驅(qū)動(dòng)程序自動(dòng)創(chuàng)建。可在/dev目錄下用ls命令查看該目錄下的內(nèi)容。(2)/lib目錄在/lib目錄下,包括了glibc鏈接庫(kù),glibc存放系統(tǒng)必要的動(dòng)態(tài)鏈接庫(kù),支持系統(tǒng)的正常啟動(dòng),包括:①ld :動(dòng)態(tài)鏈接器。②libc :主C鏈接器進(jìn)程。③libm:數(shù)學(xué)進(jìn)程,在數(shù)學(xué)函數(shù)中需要用到。④ibcrypt :密碼學(xué)進(jìn)程,多數(shù)涉及認(rèn)證的應(yīng)用程序中需要使用。完整說(shuō)明參見(jiàn)glibc使用手冊(cè),相應(yīng)的連接庫(kù)可以從編譯器的lib目錄下拷取。(3)/lib目錄在etc目錄包含很多文件。主要的子目錄如下。①/etc/rc、/etc/rc.d、/etc/rc*.d:?jiǎn)?dòng)、或改變運(yùn)行時(shí)運(yùn)行的scripts或scripts的目錄。

②/etc/passwd:用戶(hù)數(shù)據(jù)庫(kù),其中的域給出了用戶(hù)名、真實(shí)姓名、家目錄、加密的口令和用戶(hù)的其他信息。

③/etc/fstab:啟動(dòng)時(shí)mount-a命令(在/etc/rc或等效的啟動(dòng)文件中)自動(dòng)mount的文件系統(tǒng)列表。

④/etc/inittab:nit的配置文件。

⑤/etc/login.defs:login命令的配置文件。

⑥/etc/profile:登錄時(shí)執(zhí)行的文件。系統(tǒng)管理員可為所有用戶(hù)建立全局缺省環(huán)境。

⑦/etc/securetty:確認(rèn)安全終端,即哪個(gè)終端允許root登錄。⑧/etc/shells:列出可信任的shell。chsh命令允許用戶(hù)在本文件指定范圍內(nèi)改變登錄shell4.2.3使用Busybox生成工具集Busybox在設(shè)計(jì)上就充分考慮了硬件資源受限的特殊工作環(huán)境,采用一種很巧妙的辦法減少自己的體積,即所有的命令都通過(guò)“插件”的方式集中到一個(gè)可執(zhí)行文件中,在實(shí)際應(yīng)用過(guò)程中通過(guò)不同的符號(hào)鏈接來(lái)確定到底要執(zhí)行哪個(gè)操作。采用單一執(zhí)行文件的方式最大限度地共享了程序代碼,甚至連文件頭、內(nèi)存中的程序控制塊等其他操作系統(tǒng)資源都共享了,對(duì)于資源比較緊張的系統(tǒng)來(lái)說(shuō),真是最合適不過(guò)了。在busybox的編譯過(guò)程中,可以非常方便地加減它的“插件”,最后的符號(hào)鏈接也可以由編譯系統(tǒng)自動(dòng)生成。1.Busybox的配置和交叉編譯Busybox的編譯過(guò)程與內(nèi)核的編譯過(guò)程很接近,都是先makemenuconfig進(jìn)行配置,然后在make進(jìn)行編譯。(1)從/downloads/下載busybox工具。這里選擇busybox-1.1.0.tar.bz2(注:交叉編譯器用arm-linux-gcc3.4.1/3.3.2)。(2)解壓busybox-1.1.0.tar.bz2,使用命令是:tarjxvfbusybox-1.1.0.tar.bz2。(3)進(jìn)入busybox目錄,修改Makefile中的ARCH和CROSS_COMPILE,改成:ARCH?=armCROSS_COMPILE?=/usr/local/arm/3.4.1/bin/arm-linux-當(dāng)然CROSS_COMPILE可由開(kāi)發(fā)者的編譯器位置決定。(4)Makemenuconfig進(jìn)行配置,可以選擇靜態(tài)編譯,如果是動(dòng)態(tài)編譯則要拷貝相應(yīng)的庫(kù)文件,默認(rèn)配置保存即可。圖4.3配置菜單1.選擇Busybox的編譯方式:BuildOptionsBuildBusyBoxasastaticbinary(nosharedlibs)缺省配置為使用鏈接庫(kù)。2.配置交叉編譯器:BuildOptions[*]DoyouwanttobuildBusyBoxwithaCrossCompiler?(/usr/local/arm/3.4.1/bin/arm-linux-)CrossCompilerprefix3.安裝路徑:InstallationOptions(./_install)BusyBoxinstallationprefix4.配置其他工具集:ArchivalUtilitiesCoreutilsConsoleUtilitiesDebianUtilitieEditorsFindingUtilitiesInitUtilitiesLogin/PasswordManagementUtilitiesMiscellaneousUtilitiesLinuxModuleUtilitiesNetworkingUtilitiesProcessUtilitiesShellsSystemLoggingUtilitiesLinuxSystemUtilitiesInitUtilities[*]init[*]Supportreadinganinittabfile?[*]Supportrunninginitfromwithinaninitrd?5.配置其他工具集:●ArchivalUtilities工具:tar、zip、unzip●Coreutils

常用命令:basenamecatchgrpchmoddatedddfechoenvlnlsmkdirmknodmvpwdrmrmdirsleepsortsyncwcwhoami等等?!馝ditors編輯命令:viawksed等?!馞indingUtilities查找命令:findgrepxargs●Login/PasswordManagementUtilitiesLogin:gettyloginpasswd●NetworkingUtilities

網(wǎng)絡(luò)命令集:hostnameifconfiginetdnetstatpingroute●ProcessUtilities進(jìn)程命令:freepssysctltop●Shellsshell工具:ash等●SystemLoggingUtilities

日志工具:syslogdklogd

●LinuxSystemUtilities

系統(tǒng)工具:dmesgfdiskgetoptmoremountumount(5)#makedep(6)#make(7)#makeinstall之后,在busybox目錄下生成_install文件夾。其結(jié)構(gòu)(_install)為:/bin/linuxrc/sbin/usr/usr/bin/usr/sbin也可用makeallinstall命令完成編譯。2.文件系統(tǒng)打包用Busybox配置和交叉編譯創(chuàng)建的根文件系統(tǒng)還需用cramfs工具對(duì)根文件系統(tǒng)進(jìn)行打包成root.cramfs文件。步驟如下。(1)從/cramfs/下載cramfs工具。(2)解壓cramfs-1.1.tar.gz使用命令:tarzxvfcramfs-1.1.tar.gz。(3)進(jìn)入cramfs工具的根目錄執(zhí)行make。(4)Make后在cramfs工具的根目錄中就會(huì)生成一個(gè)mkcramfs文件,這就是根文件系統(tǒng)的打包工具。(5)打包,即執(zhí)行命令mkcramfs_installrootfs之后就可產(chǎn)生打包后的根文件系統(tǒng)root.cramfs。4.2.4根文件系統(tǒng)啟動(dòng)流程KERNEL起來(lái)之后,將運(yùn)行第一個(gè)進(jìn)程init,實(shí)際上執(zhí)行的為Busybox的/sbin/init。init的工作是根據(jù)/etc/inittab腳本來(lái)進(jìn)行系統(tǒng)的初始化,其格式和命令的含義如下:::runlevels:action:processsysinit:指定運(yùn)行的第一個(gè)程序/腳本。respawn:如果process字段指定的進(jìn)程不存在,則啟動(dòng)該進(jìn)程,init不等待處理結(jié)束,而是繼續(xù)掃描inittab文件中的后續(xù)進(jìn)程,當(dāng)這樣的進(jìn)程終止時(shí),init會(huì)重新啟動(dòng)它,如果這樣的進(jìn)程已存在,則什么也不做。ctrlaltdel:指定在用戶(hù)按下Ctrl-Alt-Del時(shí)執(zhí)行的命令。shutdown:當(dāng)系統(tǒng)關(guān)機(jī)時(shí),執(zhí)行相應(yīng)的進(jìn)程。restart:當(dāng)init重新啟動(dòng)時(shí),執(zhí)行相應(yīng)的進(jìn)程,通常此處所執(zhí)行的進(jìn)程就是init本身。askfirst:類(lèi)似respawn,不少系統(tǒng)上執(zhí)行的終端應(yīng)用程序的數(shù)量。注意:加上“-”的語(yǔ)句會(huì)在登錄終端之后調(diào)用/etc/目錄下的profile文件,而不加“-”的不會(huì)執(zhí)行這個(gè)腳本。[/etc]catinittab::sysinit:/etc/init.d/rcS::respawn:-/bin/sh::restart:/sbin/inittty2::askfirst:-/bin/sh::ctrlaltdel:/bin/umount-a–r::shutdown:/bin/umount-a–r:shutdown:/sbin/swapoff–a這個(gè)inittab執(zhí)行下列動(dòng)作功能如下:(1)將/etc/init.d/rcS設(shè)置成系統(tǒng)的初始化文件。(2)一直啟動(dòng)shell。(3)在虛擬終端上啟動(dòng)askfirst動(dòng)作的shell。(4)如果init重新啟動(dòng),將/sbin/init設(shè)置成它會(huì)執(zhí)行的程序。(5)告訴init,在系統(tǒng)關(guān)機(jī)或重啟的時(shí)候執(zhí)行umount命令卸載所有文件系統(tǒng),并且在卸載失敗時(shí)用只讀模式?jīng)_新安裝以保護(hù)文件系統(tǒng)。init進(jìn)程運(yùn)行腳本是/etc/init.d/rcS,在rcS中掛載文件系統(tǒng),并且執(zhí)行腳本/usr/etc/rc.local;在rc.local中繼續(xù)設(shè)置,最后運(yùn)行用戶(hù)的啟動(dòng)運(yùn)行腳本init.sh。登錄終端之前運(yùn)行腳本/etc/profile。4.3

Linux內(nèi)核及啟動(dòng)過(guò)程Linux系統(tǒng)實(shí)際上由兩個(gè)比較獨(dú)立的部分組成,即內(nèi)核部分和系統(tǒng)部分。通常一個(gè)Linux系統(tǒng)的啟動(dòng)過(guò)程如下:首先一個(gè)不隸屬于任何操作系統(tǒng)的加載程序?qū)inux部分內(nèi)核調(diào)入內(nèi)存,并將控制權(quán)交給內(nèi)存中Linux內(nèi)核的第一行代碼,加載程序的工作就完成了。此后Linux要將自己的剩余部分全部加載到內(nèi)存、初始化所有的設(shè)備、在內(nèi)存中建立好所需的數(shù)據(jù)結(jié)構(gòu)(有關(guān)進(jìn)程、設(shè)備、內(nèi)存等)。到此為止,Linux內(nèi)核的工作告一段落,內(nèi)核已經(jīng)控制了所有硬件設(shè)備。至于操作和使用這些硬件設(shè)備,則是系統(tǒng)部分任務(wù)。內(nèi)核加載設(shè)備并啟動(dòng)init守護(hù)進(jìn)程,init守護(hù)進(jìn)程會(huì)根據(jù)配置文件加載文件系統(tǒng)、配置網(wǎng)絡(luò)、服務(wù)進(jìn)程、終端等。也就是說(shuō),內(nèi)核部分初始化并控制大部分硬件設(shè)備,為內(nèi)存管理、進(jìn)程管理、設(shè)備讀、寫(xiě)等工作做好一切準(zhǔn)備;系統(tǒng)部分加載必需的設(shè)備,配置各種環(huán)境以便用戶(hù)可以使用整個(gè)系統(tǒng)。4.3.1Linux內(nèi)核結(jié)構(gòu)Linux內(nèi)核主要由五個(gè)子系統(tǒng)組成:進(jìn)程調(diào)度,內(nèi)存管理,虛擬文件系統(tǒng),網(wǎng)絡(luò)接口,進(jìn)程間通信。●進(jìn)程調(diào)度(SCHED):控制進(jìn)程對(duì)CPU的訪問(wèn)。當(dāng)需要選擇下一個(gè)進(jìn)程運(yùn)行時(shí),由調(diào)度程序選擇最值得運(yùn)行的進(jìn)程。可運(yùn)行進(jìn)程實(shí)際上是僅等待CPU資源的進(jìn)程,如果某個(gè)進(jìn)程在等待其它資源,則該進(jìn)程是不可運(yùn)行進(jìn)程。Linux使用了比較簡(jiǎn)單的基于優(yōu)先級(jí)的進(jìn)程調(diào)度算法選擇新的進(jìn)程?!駜?nèi)存管理(MM):允許多個(gè)進(jìn)程安全的共享主內(nèi)存區(qū)域。Linux的內(nèi)存管理支持虛擬內(nèi)存,即在計(jì)算機(jī)中運(yùn)行的程序,其代碼、數(shù)據(jù)、堆棧的總量可以超過(guò)實(shí)際內(nèi)存的大小,操作系統(tǒng)只是把當(dāng)前使用的程序塊保留在內(nèi)存中,其余的程序塊則保留在磁盤(pán)中。必要時(shí),操作系統(tǒng)負(fù)責(zé)在磁盤(pán)和內(nèi)存間交換程序塊。內(nèi)存管理從邏輯上分為硬件無(wú)關(guān)部分和硬件有關(guān)部分。硬件無(wú)關(guān)部分提供了進(jìn)程的映射和邏輯內(nèi)存的對(duì)換;硬件相關(guān)的部分為內(nèi)存管理硬件提供了虛擬接口?!裉摂M文件系統(tǒng)(VirtualFileSystem,VFS):隱藏了各種硬件的具體細(xì)節(jié),為所有的設(shè)備提供了統(tǒng)一的接口,VFS提供了多達(dá)數(shù)十種不同的文件系統(tǒng)。虛擬文件系統(tǒng)可以分為邏輯文件系統(tǒng)和設(shè)備驅(qū)動(dòng)程序。邏輯文件系統(tǒng)指Linux所支持的文件系統(tǒng),如ext2,fat等,設(shè)備驅(qū)動(dòng)程序指為每一種硬件控制器所編寫(xiě)的設(shè)備驅(qū)動(dòng)程序模塊。●網(wǎng)絡(luò)接口(NET):提供了對(duì)各種網(wǎng)絡(luò)標(biāo)準(zhǔn)的存取和各種網(wǎng)絡(luò)硬件的支持。網(wǎng)絡(luò)接口可分為網(wǎng)絡(luò)協(xié)議和網(wǎng)絡(luò)驅(qū)動(dòng)程序。網(wǎng)絡(luò)協(xié)議部分負(fù)責(zé)實(shí)現(xiàn)每一種可能的網(wǎng)絡(luò)傳輸協(xié)議。網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序負(fù)責(zé)與硬件設(shè)備通訊,每一種可能的硬件設(shè)備都有相應(yīng)的設(shè)備驅(qū)動(dòng)程序。●進(jìn)程間通訊(IPC):支持進(jìn)程間各種通信機(jī)制。處于中心位置的進(jìn)程調(diào)度,所有其它的子系統(tǒng)都依賴(lài)它,因?yàn)槊總€(gè)子系統(tǒng)都需要掛起或恢復(fù)進(jìn)程。一般情況下,當(dāng)一個(gè)進(jìn)程等待硬件操作完成時(shí),它被掛起;當(dāng)操作真正完成時(shí),進(jìn)程被恢復(fù)執(zhí)行。例如,當(dāng)一個(gè)進(jìn)程通過(guò)網(wǎng)絡(luò)發(fā)送一條消息時(shí),網(wǎng)絡(luò)接口需要掛起發(fā)送進(jìn)程,直到硬件成功地完成消息的發(fā)送,當(dāng)消息被成功的發(fā)送出去以后,網(wǎng)絡(luò)接口給進(jìn)程返回一個(gè)代碼,表示操作的成功或失敗。其他子系統(tǒng)以相似的理由依賴(lài)于進(jìn)程調(diào)度。各個(gè)子系統(tǒng)之間的依賴(lài)關(guān)系如下:●進(jìn)程調(diào)度與內(nèi)存管理之間的關(guān)系:這兩個(gè)子系統(tǒng)互相依賴(lài)。在多道程序環(huán)境下,程序要運(yùn)行必須為之創(chuàng)建進(jìn)程,而創(chuàng)建進(jìn)程的第一件事情,就是將程序和數(shù)據(jù)裝入內(nèi)存?!襁M(jìn)程間通信與內(nèi)存管理的關(guān)系:進(jìn)程間通信子系統(tǒng)要依賴(lài)內(nèi)存管理支持共享內(nèi)存通信機(jī)制,這種機(jī)制允許兩個(gè)進(jìn)程除了擁有自己的私有空間,還可以存取共同的內(nèi)存區(qū)域?!裉摂M文件系統(tǒng)與網(wǎng)絡(luò)接口之間的關(guān)系:虛擬文件系統(tǒng)利用網(wǎng)絡(luò)接口支持網(wǎng)絡(luò)文件系統(tǒng)(NFS),也利用內(nèi)存管理支持RAMDISK設(shè)備?!駜?nèi)存管理與虛擬文件系統(tǒng)之間的關(guān)系:內(nèi)存管理利用虛擬文件系統(tǒng)支持交換,交換進(jìn)程(swapd)定期由調(diào)度程序調(diào)度,這也是內(nèi)存管理依賴(lài)于進(jìn)程調(diào)度的唯一原因。當(dāng)一個(gè)進(jìn)程存取的內(nèi)存映射被換出時(shí),內(nèi)存管理向文件系統(tǒng)發(fā)出請(qǐng)求,同時(shí),掛起當(dāng)前正在運(yùn)行的進(jìn)程。除了這些依賴(lài)關(guān)系外,內(nèi)核中的所有子系統(tǒng)還要依賴(lài)于一些共同的資源。這些資源包括所有子系統(tǒng)都用到的過(guò)程。例如:分配和釋放內(nèi)存空間的過(guò)程,打印警告或錯(cuò)誤信息的過(guò)程,還有系統(tǒng)的調(diào)試?yán)痰鹊?。Linux內(nèi)核源代碼位于/usr/src/linux-*.*.*(*.*.*代表內(nèi)核版本,如2.4.18)目錄下。其中子目錄如下:●/include子目錄包含了建立內(nèi)核代碼時(shí)所需的大部分包含文件,這個(gè)模塊利用其他模塊重建內(nèi)核。●/init

子目錄包含了內(nèi)核的初始化代碼,這是內(nèi)核工作的開(kāi)始的起點(diǎn)?!?arch子目錄包含了所有硬件結(jié)構(gòu)特定的內(nèi)核代碼。如:i386,alpha和ARM。●/drivers子目錄包含了內(nèi)核中所有的設(shè)備驅(qū)動(dòng)程序,如:塊設(shè)備和SCSI設(shè)備。●/fs子目錄包含了所有的文件系統(tǒng)的代碼。如:ext2,vfat等?!?net子目錄包含了內(nèi)核的連網(wǎng)代碼?!?mm子目錄包含了所有內(nèi)存管理代碼?!?ipc子目錄包含了進(jìn)程間通信代碼。●/kernel子目錄包含了主內(nèi)核代碼。在Linux內(nèi)核的實(shí)現(xiàn)中,以下數(shù)據(jù)結(jié)構(gòu)使用非常頻繁?!駎ask_struct:Linux內(nèi)核利用task_struct數(shù)據(jù)結(jié)構(gòu)代表一個(gè)進(jìn)程,用task_struct指針形成一個(gè)task數(shù)組。當(dāng)建立新進(jìn)程的時(shí)候,Linux為新的進(jìn)程分配一個(gè)task_struct結(jié)構(gòu),然后將指針保存在task數(shù)組中。調(diào)度程序維護(hù)current指針,它指向當(dāng)前正在運(yùn)行的進(jìn)程?!駇m_struct:每個(gè)進(jìn)程的虛擬內(nèi)存由mm_struct結(jié)構(gòu)代表。該結(jié)構(gòu)中包含了一組指向vm-area_struct結(jié)構(gòu)的指針,vm-area_struct結(jié)構(gòu)描述了虛擬內(nèi)存的一個(gè)區(qū)域?!駃node:虛擬文件系統(tǒng)(VFS)中的文件、目錄等均由對(duì)應(yīng)的索引節(jié)點(diǎn)(inode)代表。每個(gè)VFS索引節(jié)點(diǎn)中的內(nèi)容由文件系統(tǒng)專(zhuān)屬的例程提供。VFS索引節(jié)點(diǎn)只存在于內(nèi)核內(nèi)存中,實(shí)際保存于VFS的索引節(jié)點(diǎn)高速緩存中。如果兩個(gè)進(jìn)程用相同的進(jìn)程打開(kāi),則可以共享inade的數(shù)據(jù)結(jié)構(gòu),這種共享是通過(guò)兩個(gè)進(jìn)程中數(shù)據(jù)塊指向相同的inode完成。4.3.2

Linux內(nèi)核配置、編譯

1.Linux內(nèi)核的配置系統(tǒng)的組成(1)Makefile:分布在

Linux

內(nèi)核源代碼中的

Makefile,定義

Linux

內(nèi)核的編譯規(guī)則?!耥攲?/p>

Makefile

讀取

.config中的配置選項(xiàng),如:CROSS_COMPILE?=/usr/local/arm-linux/bin/arm-linux-是指定編譯內(nèi)核所用的編譯器。include

arch/(ARCH)/Makefile包含了特定

CPU

體系結(jié)構(gòu)下的

Makefile,指定了平臺(tái)相關(guān)的信息?!窀鱾€(gè)子目錄下的Makefile:比如drivers/Makefile,負(fù)責(zé)所在子目錄下源代碼的編譯管理。

(2)配置文件:給用戶(hù)提供配置選擇的功能?!?config:內(nèi)核配置文件,包含由用戶(hù)選擇的配置選項(xiàng),用來(lái)存放內(nèi)核配置后的結(jié)果(如makemenuconfig)?!馬ules.make:規(guī)則文件,被所有的Makefile使用。

(3)配置工具:包括配置命令解釋器(對(duì)配置腳本中使用的配置命令進(jìn)行解釋?zhuān)?。常用的Linux內(nèi)核的配置工具按其配置用戶(hù)界面的不同主要有以下3種:①基于字符的界面make

config:進(jìn)入命令行,可以一行一行的配置,但使用不十分方便。②基于

Ncurses

的文本模式圖形用戶(hù)界面make

menuconfig:大多數(shù)開(kāi)發(fā)人員使用的Linux內(nèi)核編譯菜單,使用方便。③基于

Xwindows

圖形界面的用戶(hù)配置界面make

xconfig:在2.4.X以及以前版本中xconfig菜單是基于TCL/TK的圖形庫(kù)的。2.Linux內(nèi)核的配置與裁減所有Linux內(nèi)核配置都是通過(guò)Config.in經(jīng)由不同腳本解釋器產(chǎn)生.config。而目前剛剛推出的2.6.X內(nèi)核用QT圖形庫(kù)。由KConfig經(jīng)由腳本解釋器產(chǎn)生。這兩版本差別還挺大。2.6.X的xconfig菜單結(jié)構(gòu)清晰,使用也更方便。但基于目前2.4.X版本比較成熟,穩(wěn)定,用的最多。xconfig界面比較友好,易掌握。但它卻沒(méi)有menuconfig菜單穩(wěn)定。所以大多數(shù)嵌入式開(kāi)發(fā)人還是使用以2.4.X版本為基礎(chǔ)的menuconfig菜單進(jìn)行相關(guān)Linux內(nèi)核的配置。在啟動(dòng)配置菜單后,選擇相應(yīng)的配置時(shí),有三種選擇方式,它們分別代表的含義如下?!馧——不將該功能編譯進(jìn)內(nèi)核●Y——將該功能編譯進(jìn)內(nèi)核●M——將該功能編譯成可以在需要時(shí)動(dòng)態(tài)插入到內(nèi)核中的模塊

從/pub/linux/kernel/v2.4/linux-2.4.24.tar.gz下載內(nèi)核源碼,然后復(fù)制linux-2.4.24.tar.gz到/usr/src目錄下,并解壓linux-2.4.24.tar.gz(tarzxvflinux-2.4.24.tar.gz)。再進(jìn)入目錄/usr/src/linux-2.4.24,,執(zhí)行makemrproper命令,其目的是清除原先此目錄下殘留的.config和.o文件(object文件),如果是第一次編譯內(nèi)核,那么這一步就可以省略,但是如果已經(jīng)編譯過(guò)多次內(nèi)核的話(huà),這一步一定要,不然以后出現(xiàn)很多小問(wèn)題。而后再執(zhí)行makemenuconfig命令,進(jìn)入圖形配置界面,可按需要對(duì)Linux內(nèi)核進(jìn)行配置裁減,如圖4.4所示。下面以Linux2.4.X版本為例詳細(xì)介紹使用makemenuconfig對(duì)linux內(nèi)核的配置過(guò)程。運(yùn)行makemenuconfig進(jìn)入配置界面,各選項(xiàng)如下。(1)Codematurityleveloptions:代碼成熟等級(jí)。此處只有一個(gè)選項(xiàng):promptfordevelopmentand/orincompletecode/drivers,若為試驗(yàn)階段,比如khttpd、IPv6等,則該項(xiàng)選擇Y;否則選擇N。(2)Loadablemodulesupport:對(duì)模塊的支持。有三個(gè)選項(xiàng):●Enableloadablemodulesupport:除非準(zhǔn)備把所有需要的內(nèi)容都編譯到內(nèi)核里面,否則該選項(xiàng)應(yīng)該是必選的?!馭etversioninFORMationonallmodulesymbols:可以不選它?!馣ernelmoduleloader:讓內(nèi)核在啟動(dòng)時(shí)有自己裝入必需模塊的能力,建議選上。(3)SystemType:系統(tǒng)類(lèi)型。主要選項(xiàng)如下:●Processorfamily:選擇所需CPU類(lèi)型。●HighMemorySupport:大容量?jī)?nèi)存的支持。可支持到4G、64G,一般可以不選?!馦athemulation:協(xié)處理器仿真?,F(xiàn)在一般不選?!馦TTRsupport:MTTR支持??刹贿x?!馭ymmetricmulti-processingsupport:多處理支持。若有多個(gè)CPU必選,否則不選。圖4.4makemenuconfig的圖形界面(4)Generalsetup:普通的屬性設(shè)置。主要選項(xiàng)如下:●Networkingsupport:網(wǎng)絡(luò)支持。必選,即使沒(méi)有網(wǎng)卡也建議選上?!馪CIsupport:PCI支持。如果使用了PCI的卡,當(dāng)然必選?!馪CIaccessmode:PCI存取模式。有BIOS、Direct和Any選項(xiàng),一般選Any?!馭upportforhot-pluggabeldevices:熱插拔設(shè)備支持??刹贿x?!馪CMCIA/CardBussupport:PCMCIA/CardBus支持。有PCMCIA,必選?!馭ystemVIPCBSDProcessAccountingSysctlsupport:如果不使用BSD,選缺省。

●PowerManagementsupport:電源管理支持?!馎dvancedPowerManagementBIOSsupport:高級(jí)電源管理BIOS支持。(5)MemoryTechnologyDevice(MTD):MTD設(shè)備支持??刹贿x。(6)Parallelportsupport并口支持。如果不打算使用并口,就不選。(7)PlugandPlayconfiguration即插即用支持。一般選。(8)Blockdevices塊設(shè)備支持。根據(jù)配置系統(tǒng)的應(yīng)用情況來(lái)選。(9)Networkingoptions:網(wǎng)絡(luò)選項(xiàng)。配置的是網(wǎng)絡(luò)協(xié)議。通常選中TCP/IPnetworking。(10)TelephonySupport電話(huà)支持。linux下可支持電話(huà)卡,可在IP上使用普通的電話(huà)提供語(yǔ)音服務(wù)了。(11)ATA/IDE/MFM/RLLsupport:各種接口的硬盤(pán)/光驅(qū)/磁帶/軟盤(pán)支持的,使用缺省的選項(xiàng)。(12)SCSIsupport:SCSI設(shè)備的支持。若沒(méi)有SCSI的設(shè)備,則不選用。(13)FusionMPTdevicesupport:需要FusionMPT兼容PCI適配器,不用選。(14)I2Cdevicesupport:I2C接口適配器支持。(15)Networkdevicesupport:網(wǎng)絡(luò)設(shè)備支持。選擇了所用到的網(wǎng)卡時(shí),一般編譯到內(nèi)核,再選Y。(16)AmateurRadiosupport:配置業(yè)余無(wú)線(xiàn)廣播。(17)IrDA(infrared)support:紅外線(xiàn)支持。(18)ISDNsubsystem:如果使用ISDN上網(wǎng),則必選。(19)OldCD-ROMdrivers(notSCSI、notIDE):若用IDE的CD-ROM可不用選。(20)Characterdevices:字符設(shè)備。一般使用缺省設(shè)置,可按需要修改。(21)Filesystems:文件系統(tǒng)。一般使用缺省設(shè)置,可按需要修改。(22)Consoledrivers:控制臺(tái)驅(qū)動(dòng)。一般使用VGAtextconsole,標(biāo)準(zhǔn)的80*25的文本控制臺(tái)。(23)Sound:聲卡驅(qū)動(dòng)。最好在列表中選擇所用的聲卡驅(qū)動(dòng),否則就試用OSS。(24)USBsupprot:USB支持。按需要選擇。(25)Kernelhacking:配置了這項(xiàng),即使在系統(tǒng)崩潰時(shí),也可以進(jìn)行一定的工作了。普通用戶(hù)是用不著這個(gè)功能的。配置完后,存盤(pán)退出。3.Linux內(nèi)核的編譯在完成內(nèi)核的裁減之后,內(nèi)核的編譯就只要執(zhí)行以下幾條命令:●makedep:對(duì)內(nèi)核原代碼的文件進(jìn)行完整性和依賴(lài)性進(jìn)行檢驗(yàn),確保關(guān)鍵文件在正確的位置?!駇akeclean:編譯內(nèi)核之前先把環(huán)境給清理干凈。有時(shí)也可用makerealclean或makemrproper來(lái)徹底清除相關(guān)依賴(lài),保證沒(méi)有不正確的.o文件存在?!駇akezImage:創(chuàng)建內(nèi)核鏡像文件●makemodules:創(chuàng)建內(nèi)核模塊,若不創(chuàng)建內(nèi)核模塊,這步可以不要。下面是進(jìn)行makemodules_install的操作,安裝module的過(guò)程如下。(1)cp/usr/src/linux/arch/i386/boot/bzImage/boot/bzImage-2.4.24??截愋聝?nèi)核文件“/usr/src/linux/arch/i386/boot/bzImage”到啟動(dòng)目錄,并改為合適的名字。(2)makeinstall:把相關(guān)文件拷貝到默認(rèn)的目錄。在給嵌入式設(shè)備編譯時(shí)這步可以不要。因?yàn)榫唧w的內(nèi)核安裝還需要你手工進(jìn)行。(3)修改/boot/grub/grub.conf文件的內(nèi)容,如下:default=0timeout=30splashimage=(hd0,6)titleRedHatLinux(2.4.20-8)root(hd0,0)kernel/vmlinuz-2.4.20-8roroot=/LABEL/initrd/initrd-2.4.20-8.imgtitleRedHatLinux(2.4.24)root(hd0,0)kernelvmlinuz-2.4.24roroot=/dev/hda0initrd/initrd-2.4.24.img

設(shè)置完成,然后就可以重啟計(jì)算機(jī),看是否能進(jìn)入新編譯的內(nèi)核了。4.3.3基于ARM開(kāi)發(fā)板的Linux內(nèi)核移植1.Linux移植準(zhǔn)備●先到.uk上下載Linux2.6.0內(nèi)核及其關(guān)于ARM平臺(tái)的補(bǔ)?。ㄈ纾篜atch-2.6.0-rmk1.gz)?!窠oLinux2.6.0打補(bǔ)?。簔cat../patch-2.6.0-rmk1.gz|patch–p1(前面../表示補(bǔ)丁文件放在內(nèi)核文件上一層目錄)●準(zhǔn)備交叉編譯環(huán)境。交叉編譯環(huán)境工具鏈一般包括binutils(含AS匯編器,LD鏈接器等),arm-gcc,glibc等?!裥薷膬?nèi)核目錄下的makefile文件,主要是以下幾行:注釋掉ARCH:=$(shelluname–m|sed–es/i.86/i386/-es/sun4u/sparc64/-es/arm.*/arm/-es/sa110/arm/)這一行。ARCH:=改為ARCH:=armCROSS_COMPILE:=改為CROSS_COMPILE=交叉編譯工

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論