99精品久久这里只有精品,三上悠亚免费一区二区在线,91精品福利一区二区,爱a久久片,无国产精品白浆免费视,中文字幕欧美一区,爽妇网国产精品,国产一级做a爱免费观看,午夜一级在线,国产精品偷伦视频免费手机播放

    <del id="eyo20"><dfn id="eyo20"></dfn></del>
  • <small id="eyo20"><abbr id="eyo20"></abbr></small>
      <strike id="eyo20"><samp id="eyo20"></samp></strike>
    • 首頁 > 文章中心 > 正文

      ARM Linu啟動過程

      前言:本站為你精心整理了ARM Linu啟動過程范文,希望能為你的創(chuàng)作提供參考價值,我們的客服老師可以幫助你提供個性化的參考范文,歡迎咨詢。

      摘要:嵌入式Linux的可移植性使得我們可以在各種電子產(chǎn)品上看到它的身影。對于不同體系結(jié)構(gòu)的處理器來說Linux的啟動過程也有所不同。本文以S3C2410ARM處理器為例,詳細(xì)分析了系統(tǒng)上電后bootloader的執(zhí)行流程及ARMLinux的啟動過程。

      關(guān)鍵詞:ARMLinuxbootloader啟動過程

      Abstract:

      WecanseeembeddedLinuxinkindsofelectronicproductsbecauseofitsportability.Linux’sstart-upprocedurefordifferentprocessorsisalsodifferent.ThispaperprovidestheanalysisofbootloaderexecutionprocessandLinuxkernelstart-upprocedure-takingtheS3C2410ARMprocessorasexample.

      Keywords:ARMLinuxbootloaderstart-upprocedure

      1.引言

      Linux最初是由瑞典赫爾辛基大學(xué)的學(xué)生LinusTorvalds在1991年開發(fā)出來的,之后在GNU的支持下,Linux獲得了巨大的發(fā)展。雖然Linux在桌面PC機(jī)上的普及程度遠(yuǎn)不及微軟的Windows操作系統(tǒng),但它的發(fā)展速度之快、用戶數(shù)量的日益增多,也是微軟所不能輕視的。而近些年來Linux在嵌入式領(lǐng)域的迅猛發(fā)展,更是給Linux注入了新的活力。

      一個嵌入式Linux系統(tǒng)從軟件角度看可以分為四個部分[1]:引導(dǎo)加載程序(bootloader),

      Linux內(nèi)核,文件系統(tǒng),應(yīng)用程序。

      其中bootloader是系統(tǒng)啟動或復(fù)位以后執(zhí)行的第一段代碼,它主要用來初始化處理器及外設(shè),然后調(diào)用Linux內(nèi)核。Linux內(nèi)核在完成系統(tǒng)的初始化之后需要掛載某個文件系統(tǒng)做為根文件系統(tǒng)(RootFilesystem)。根文件系統(tǒng)是Linux系統(tǒng)的核心組成部分,它可以做為Linux系統(tǒng)中文件和數(shù)據(jù)的存儲區(qū)域,通常它還包括系統(tǒng)配置文件和運(yùn)行應(yīng)用軟件所需要的庫。應(yīng)用程序可以說是嵌入式系統(tǒng)的“靈魂”,它所實(shí)現(xiàn)的功能通常就是設(shè)計該嵌入式系統(tǒng)所要達(dá)到的目標(biāo)。如果沒有應(yīng)用程序的支持,任何硬件上設(shè)計精良的嵌入式系統(tǒng)都沒有實(shí)用意義。

      從以上分析我們可以看出bootloader和Linux內(nèi)核在嵌入式系統(tǒng)中的關(guān)系和作用。Bootloader在運(yùn)行過程中雖然具有初始化系統(tǒng)和執(zhí)行用戶輸入的命令等作用,但它最根本的功能就是為了啟動Linux內(nèi)核。在嵌入式系統(tǒng)開發(fā)的過程中,很大一部分精力都是花在bootloader和Linux內(nèi)核的開發(fā)或移植上。如果能清楚的了解bootloader執(zhí)行流程和Linux的啟動過程,將有助于明確開發(fā)過程中所需的工作,從而加速嵌入式系統(tǒng)的開發(fā)過程。而這正是本文的所要研究的內(nèi)容。

      2.Bootloader

      2.1Bootloader的概念和作用Bootloader是嵌入式系統(tǒng)的引導(dǎo)加載程序,它是系統(tǒng)上電后運(yùn)行的第一段程序,其作用類似于PC機(jī)上的BIOS。在完成對系統(tǒng)的初始化任務(wù)之后,它會將非易失性存儲器(通常是Flash或DOC等)中的Linux內(nèi)核拷貝到RAM中去,然后跳轉(zhuǎn)到內(nèi)核的第一條指令處繼續(xù)執(zhí)行,從而啟動Linux內(nèi)核。由此可見,bootloader和Linux內(nèi)核有著密不可分的聯(lián)系,要想清楚的了解Linux內(nèi)核的啟動過程,我們必須先得認(rèn)識bootloader的執(zhí)行過程,這樣才能對嵌入式系統(tǒng)的整個啟過程有清晰的掌握。

      2.2Bootloader的執(zhí)行過程不同的處理器上電或復(fù)位后執(zhí)行的第一條指令地址并不相同,對于ARM處理器來說,該地址為0x00000000。對于一般的嵌入式系統(tǒng),通常把Flash等非易失性存儲器映射到這個地址處,而bootloader就位于該存儲器的最前端,所以系統(tǒng)上電或復(fù)位后執(zhí)行的第一段程序便是bootloader。而因為存儲bootloader的存儲器不同,bootloader的執(zhí)行過程也并不相同,下面將具體分析。

      嵌入式系統(tǒng)中廣泛采用的非易失性存儲器通常是Flash,而Flash又分為NorFlash和NandFlash兩種。它們之間的不同在于:NorFlash支持芯片內(nèi)執(zhí)行(XIP,eXecuteInPlace),這樣代碼可以在Flash上直接執(zhí)行而不必拷貝到RAM中去執(zhí)行。而NandFlash并不支持XIP,所以要想執(zhí)行NandFlash上的代碼,必須先將其拷貝到RAM中去,然后跳到RAM中去執(zhí)行。實(shí)際應(yīng)用中的bootloader根據(jù)所需功能的不同可以設(shè)計得很復(fù)雜,除完成基本的初始化系統(tǒng)和調(diào)用Linux內(nèi)核等基本任務(wù)外,還可以執(zhí)行很多用戶輸入的命令,比如設(shè)置Linux啟動參數(shù),給Flash分區(qū)等;也可以設(shè)計得很簡單,只完成最基本的功能。但為了能達(dá)到啟動Linux內(nèi)核的目的,所有的bootloader都必須具備以下功能[2]:

      1)初始化RAM

      因為Linux內(nèi)核一般都會在RAM中運(yùn)行,所以在調(diào)用Linux內(nèi)核之前bootloader必須設(shè)置和初始化RAM,為調(diào)用Linux內(nèi)核做好準(zhǔn)備。初始化RAM的任務(wù)包括設(shè)置CPU的控制寄存器參數(shù),以便能正常使用RAM以及檢測RAM大小等。

      2)初始化串口串口在Linux的啟動過程中有著非常重要的作用,它是Linux內(nèi)核和用戶交互的方式之一。Linux在啟動過程中可以將信息通過串口輸出,這樣便可清楚的了解Linux的啟動過程。雖然它并不是bootloader必須要完成的工作,但是通過串口輸出信息是調(diào)試bootloader和Linux內(nèi)核的強(qiáng)有力的工具,所以一般的bootloader都會在執(zhí)行過程中初始化一個串口做為調(diào)試端口。

      3)檢測處理器類型

      Bootloader在調(diào)用Linux內(nèi)核前必須檢測系統(tǒng)的處理器類型,并將其保存到某個常量中提供給Linux內(nèi)核。Linux內(nèi)核在啟動過程中會根據(jù)該處理器類型調(diào)用相應(yīng)的初始化程序。

      4)設(shè)置Linux啟動參數(shù)

      Bootloader在執(zhí)行過程中必須設(shè)置和初始化Linux的內(nèi)核啟動參數(shù)。目前傳遞啟動參數(shù)主要采用兩種方式:即通過structparam_struct和structtag(標(biāo)記列表,taggedlist)兩種結(jié)構(gòu)傳遞。structparam_struct是一種比較老的參數(shù)傳遞方式,在2.4版本以前的內(nèi)核中使用較

      多。從2.4版本以后Linux內(nèi)核基本上采用標(biāo)記列表的方式。但為了保持和以前版本的兼容性,它仍支持structparam_struct參數(shù)傳遞方式,只不過在內(nèi)核啟動過程中它將被轉(zhuǎn)換成標(biāo)記列表方式。

      標(biāo)記列表方式是種比較新的參數(shù)傳遞方式,它必須以ATAG_CORE開始,并以ATAG_NONE結(jié)尾。中間可以根據(jù)需要加入其他列表。Linux內(nèi)核在啟動過程中會根據(jù)該啟動參數(shù)進(jìn)行相應(yīng)的初始化工作。

      5)調(diào)用Linux內(nèi)核映像

      Bootloader完成的最后一項工作便是調(diào)用Linux內(nèi)核。如果Linux內(nèi)核存放在Flash中,并且可直接在上面運(yùn)行(這里的Flash指NorFlash),那么可直接跳轉(zhuǎn)到內(nèi)核中去執(zhí)行。但由于在Flash中執(zhí)行代碼會有種種限制,而且速度也遠(yuǎn)不及RAM快,所以一般的嵌入式系統(tǒng)都是將Linux內(nèi)核拷貝到RAM中,然后跳轉(zhuǎn)到RAM中去執(zhí)行。不論哪種情況,在跳到Linux內(nèi)核執(zhí)行之前CUP的寄存器必須滿足以下條件:r0=0,r1=處理器類型,r2=標(biāo)記列表在RAM中的地址。

      .Linux內(nèi)核的啟動過程

      在bootloader將Linux內(nèi)核映像拷貝到RAM以后,可以通過下例代碼啟動Linux內(nèi)核:call_linux(0,machine_type,kernel_params_base)。

      其中,machine_tpye是bootloader檢測出來的處理器類型,kernel_params_base是啟動參數(shù)在RAM的地址。通過這種方式將Linux啟動需要的參數(shù)從bootloader傳遞到內(nèi)核。Linux內(nèi)核有兩種映像:一種是非壓縮內(nèi)核,叫Image,另一種是它的壓縮版本,叫zImage。根據(jù)內(nèi)核映像的不同,Linux內(nèi)核的啟動在開始階段也有所不同。zImage是Image經(jīng)過壓縮形成的,所以它的大小比Image小。但為了能使用zImage,必須在它的開頭加上解壓縮的代碼,將zImage解壓縮之后才能執(zhí)行,因此它的執(zhí)行速度比Image要慢。但考慮到嵌入式系統(tǒng)的存儲空容量一般比較小,采用zImage可以占用較少的存儲空間,因此犧牲一點(diǎn)性能上的代價也是值得的。所以一般的嵌入式系統(tǒng)均采用壓縮內(nèi)核的方式。

      對于ARM系列處理器來說,zImage的入口程序即為arch/arm/boot/compressed/head.S。它依次完成以下工作:開啟MMU和Cache,調(diào)用decompress_kernel()解壓內(nèi)核,最后通過調(diào)用call_kernel()進(jìn)入非壓縮內(nèi)核Image的啟動。下面將具體分析在此之后Linux內(nèi)核的啟動過程。

      3.1Linux內(nèi)核入口

      Linux非壓縮內(nèi)核的入口位于文件/arch/arm/kernel/head-armv.S中的stext段。該段的基地址就是壓縮內(nèi)核解壓后的跳轉(zhuǎn)地址。如果系統(tǒng)中加載的內(nèi)核是非壓縮的Image,那么bootloader將內(nèi)核從Flash中拷貝到RAM后將直接跳到該地址處,從而啟動Linux內(nèi)核。不同體系結(jié)構(gòu)的Linux系統(tǒng)的入口文件是不同的,而且因為該文件與具體體系結(jié)構(gòu)有關(guān),所以一般均用匯編語言編寫[3]。對基于ARM處理的Linux系統(tǒng)來說,該文件就是head-armv.S。該程序通過查找處理器內(nèi)核類型和處理器類型調(diào)用相應(yīng)的初始化函數(shù),再建立頁表,最后跳轉(zhuǎn)到start_kernel()函數(shù)開始內(nèi)核的初始化工作。

      檢測處理器內(nèi)核類型是在匯編子函數(shù)__lookup_processor_type中完成的。通過以下代碼可實(shí)現(xiàn)對它的調(diào)用:bl__lookup_processor_type。__lookup_processor_type調(diào)用結(jié)束返回原程序時,會將返回結(jié)果保存到寄存器中。其中r8保存了頁表的標(biāo)志位,r9保存了處理器的ID號,r10保存了與處理器相關(guān)的struproc_info_list結(jié)構(gòu)地址。

      檢測處理器類型是在匯編子函數(shù)__lookup_architecture_type中完成的。與__lookup_processor_type類似,它通過代碼:“bl__lookup_processor_type”來實(shí)現(xiàn)對它的調(diào)用。該函數(shù)返回時,會將返回結(jié)構(gòu)保存在r5、r6和r7三個寄存器中。其中r5保存了RAM的起始基地址,r6保存了I/O基地址,r7保存了I/O的頁表偏移地址。當(dāng)檢測處理器內(nèi)核和處理器類型結(jié)束后,將調(diào)用__create_page_tables子函數(shù)來建立頁表,它所要做的工作就是將RAM基地址開始的4M空間的物理地址映射到0xC0000000開始的虛擬地址處。對筆者的S3C2410開發(fā)板而言,RAM連接到物理地址0x30000000處,當(dāng)調(diào)用__create_page_tables結(jié)束后0x30000000~0x30400000物理地址將映射到0xC0000000~0xC0400000虛擬地址處。

      當(dāng)所有的初始化結(jié)束之后,使用如下代碼來跳到C程序的入口函數(shù)start_kernel()處,開始之后的內(nèi)核初始化工作:

      bSYMBOL_NAME(start_kernel)

      3.2start_kernel函數(shù)

      start_kernel是所有Linux平臺進(jìn)入系統(tǒng)內(nèi)核初始化后的入口函數(shù),它主要完成剩余的與硬件平臺相關(guān)的初始化工作,在進(jìn)行一系列與內(nèi)核相關(guān)的初始化后,調(diào)用第一個用戶進(jìn)程-init進(jìn)程并等待用戶進(jìn)程的執(zhí)行,這樣整個Linux內(nèi)核便啟動完畢。該函數(shù)所做的具體工作有[4][5]

      1)調(diào)用setup_arch()函數(shù)進(jìn)行與體系結(jié)構(gòu)相關(guān)的第一個初始化工作;

      對不同的體系結(jié)構(gòu)來說該函數(shù)有不同的定義。對于ARM平臺而言,該函數(shù)定義在arch/arm/kernel/Setup.c。它首先通過檢測出來的處理器類型進(jìn)行處理器內(nèi)核的初始化,然后通過bootmem_init()函數(shù)根據(jù)系統(tǒng)定義的meminfo結(jié)構(gòu)進(jìn)行內(nèi)存結(jié)構(gòu)的初始化,最后調(diào)用paging_init()開啟MMU,創(chuàng)建內(nèi)核頁表,映射所有的物理內(nèi)存和IO空間。

      2)創(chuàng)建異常向量表和初始化中斷處理函數(shù);

      3)初始化系統(tǒng)核心進(jìn)程調(diào)度器和時鐘中斷處理機(jī)制;

      4)初始化串口控制臺(serial-console);

      ARM-Linux在初始化過程中一般都會初始化一個串口做為內(nèi)核的控制臺,這樣內(nèi)核在啟動過程中就可以通過串口輸出信息以便開發(fā)者或用戶了解系統(tǒng)的啟動進(jìn)程。

      5)創(chuàng)建和初始化系統(tǒng)cache,為各種內(nèi)存調(diào)用機(jī)制提供緩存,包括;動態(tài)內(nèi)存分配,虛擬文件系統(tǒng)(VirtualFileSystem)及頁緩存。

      6)初始化內(nèi)存管理,檢測內(nèi)存大小及被內(nèi)核占用的內(nèi)存情況;

      7)初始化系統(tǒng)的進(jìn)程間通信機(jī)制(IPC);

      當(dāng)以上所有的初始化工作結(jié)束后,start_kernel()函數(shù)會調(diào)用rest_init()函數(shù)來進(jìn)行最后的初始化,包括創(chuàng)建系統(tǒng)的第一個進(jìn)程-init進(jìn)程來結(jié)束內(nèi)核的啟動。Init進(jìn)程首先進(jìn)行一系列的硬件初始化,然后通過命令行傳遞過來的參數(shù)掛載根文件系統(tǒng)。最后init進(jìn)程會執(zhí)行用戶傳遞過來的“init=”啟動參數(shù)執(zhí)行用戶指定的命令,或者執(zhí)行以下幾個進(jìn)程之一:

      execve("/sbin/init",argv_init,envp_init);

      execve("/etc/init",argv_init,envp_init);

      execve("/bin/init",argv_init,envp_init);

      execve("/bin/sh",argv_init,envp_init)。

      當(dāng)所有的初始化工作結(jié)束后,cpu_idle()函數(shù)會被調(diào)用來使系統(tǒng)處于閑置(idle)狀態(tài)并等待用戶程序的執(zhí)行。至此,整個Linux內(nèi)核啟動完畢。

      4.結(jié)論

      Linux內(nèi)核是一個非常龐大的工程,經(jīng)過十多年的發(fā)展,它已從從最初的幾百KB大小發(fā)展到現(xiàn)在的幾百兆。清晰的了解它執(zhí)行的每一個過程是件非常困難的事。但是在嵌入式開發(fā)過程中,我們并不需要十分清楚linux的內(nèi)部工作機(jī)制,只要適當(dāng)修改linux內(nèi)核中那些與硬件相關(guān)的部分,就可以將linux移植到其它目標(biāo)平臺上。通過對linux的啟動過程的分析,我們可以看出哪些是和硬件相關(guān)的,哪些是linux內(nèi)核內(nèi)部已實(shí)現(xiàn)的功能,這樣在移植linux的過程中便有所針對。而linux內(nèi)核的分層設(shè)計將使linux的移植變得更加容易。

      參考文獻(xiàn)

      [1]詹榮開.嵌入式系統(tǒng)bootloader技術(shù)內(nèi)幕[EB/OL]./developerworks/cn/linux/l-btloader/index.html,2003.12.

      [2]RussellKing.BootingARMLinux[Z].LinuxDocumentation.May2002

      [3]劉淼.嵌入式系統(tǒng)接口設(shè)計與Linux驅(qū)動程序開發(fā)[M].北京航空航天大學(xué)出版社.2006.6

      [4]WilliamGatliff.TheLinux2.4Kernel’sStartupProcedure[DB/CD].2002EmbeddedSystemConferenceSanFrancisco,March..2002

      [5]ClaudiaSalzbergRodriguez,GordonFischer,StevenSmolski.Linux內(nèi)核編程[M].陳莉君,賀炎,劉霞林.機(jī)械工業(yè)出版社.2006.7

      91尤物在线看| v一区无码内射国产| 欧美亚洲日韩国产人成在线播放| 国产免费久久精品国产传媒| 99免费视频精品| 日本一区二区三区丰满熟女| 蜜臀av在线播放一区二区三区| 日本护士吞精囗交gif| 99精品久久久中文字幕| 中文亚洲一区二区三区| 国产欧美日韩一区二区加勒比| 国产呦系列呦交| 日韩一区二区不卡av| 亚洲性av少妇中文字幕| 亚洲精品一区二区国产精华液| 人妻丰满熟妇av无码区免| 免青青草免费观看视频在线| 久久狼人国产综合精品| 国内精品久久久久久99| 九九视频在线观看视频6| 国产呦系列呦交| 久久中文字幕暴力一区| 人与禽性视频77777| 中文字幕在线亚洲一区二区三区 | 日韩精品人妻久久久一二三| 日本不卡一区二区三区在线| 精品九九视频| 经典黄色一区二区三区| 亚洲香蕉成人av网站在线观看| 蜜臀av免费一区二区三区| 国产日韩亚洲中文字幕| 精品国产一区二区三区18p| 国产国拍亚洲精品mv在线观看| AV教师一区高清| 国产精品久久av高潮呻吟| 国产v片在线播放免费无码| 国产成人免费a在线视频| 国产一区二区三区免费主播| 蜜桃av在线免费网站| 亚洲av日韩av高潮潮喷无码 | 亚洲va中文字幕无码|