歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> ARM 平台上的Linux系統啟動流程

ARM 平台上的Linux系統啟動流程

日期:2017/2/28 14:02:11   编辑:Linux教程

  開始學習嵌入式開發就一直在使用Linux系統作為學習的平台,到現在無論是PC機還是ARM開發板都已經能順利地跑起了Linux系統,但是對Linux 的啟動流程還是不甚了解。於是開始各種百度谷歌,當然看到了各路大神寫的介紹。總的來說就是:bootloader ---->kernel---->root filesystem,當然還介紹了哪個階段完成了哪些工作。比如bootloader 是一上電就拿到cpu 的控制權的,而bootloader實現了硬件的初始化。bootloader俨然就成了power on 之後”第一個吃螃蟹”的代碼。

  談到這就得想到硬件機制是如何滿足這個功能的了。就拿S3C2440 這個芯片來說(我的硬件平台就是拿這個芯片作為主芯片),CPU內部集成了一塊容量為4KB 的 sram (又叫stapping stone 墊腳石),當系統一上電,NAND controler 就自動地將nand flash 裡的前4K內容復制到墊腳石裡,而PC 指針一上電就指向墊腳石的起始地址0x00000000。這樣這一部分的代碼就可以得到執行。可以想象,如果這一部分的代碼就是bootloader 的一部分,那一上電bootloader 不就可以得到運行了麼?事實確實如此,在嵌入式Linux的軟件系統中,nandflash前面一部分代碼往往就是bootloader ,然後就是kernel, 再接著就是根文件系統。

  說了這麼多,好像都沒說到啟動流程啊,別著急,咱慢慢談,所謂磨刀不誤砍柴工嘛。

  要說啟動流程,如果只是簡單的介紹從哪到哪,誰干了啥啥,得到的結果可能只是只知其然不知其所以然。個人覺得隨著CPU的PC指針走,循著代碼的足跡才能把整個流程理清楚,當找到了代碼的執行過程,再分析一下代碼,自然知道了哪個部分完成了哪些事,更重要的是為代碼的移植打下了堅實的基礎。自然這個過程是痛苦和枯燥的,甚至是看代碼看了幾天也沒弄明白,不過這也是一種鍛煉。好了不扯了,馬上進入主題。

bootloder :

  前面說了,bootloader一上電就拿到了cpu 的使用權,它當然得干一些初始化的工作啊,比如關閉看門狗、設置cpu 的運行模式、設置堆棧等等比較急迫的事情。當然還要對主板的一些其他硬件進行簡單的初始化 比如網卡,顯示屏,nand flash 等等的初始化工作,最後還要負責把Linux內核加載到內存中。正所謂責任和權力是並存的嘛,你得到了權益,當然就得付出。當bootloader 完成它的使命之後就會把cpu 的使用權交給下一部分代碼:kernel 。

kernel:

  在討論kernel 是如何啟動之前,先了解kernel 的組成結構以及是如何得來的。

  下面這張圖是內核編譯即將結束時顯示的信息:

下面的這張圖說明了上面的編譯過程,

  可以看到,當內核源文件編譯鏈接成 vmlinux 文件以後還進行了幾個模塊的編譯和鏈接。其中vmlinux 是ELF格式的object文件,這種文件只是各個源代碼經過連接以後的得到的文件,並不能在arm平台上運行。經過objcopy這個工具轉換以後,得到了二進制格式文件Image,Image文件相比於vmlinux 文件,除了格式不同以外,還被去除了許多注釋和調試的信息。Image文件經過壓縮以後得到了piggy.gz ,這個文件僅僅是Image的壓縮版,並無其他不同。接著編譯生成另外幾個模塊文件misc.o big_endian.o head.o head-xscale.o,這幾個文件組成一個叫bootstrap loader 的組件,又叫引導程序。編譯生成 piggy.o 文件。最後piggy.o文件和bootstrap loader 組成一個bootable kernel Image 文件(可啟動文件)。

  可以看到最後得到的可執行文件就是上圖最右邊那個,這也是我們最後燒寫到開發板的鏡像。其中piggy.o 就是內核鏡像,而剩下的幾個文件就組成了引導程序。  

  下面開始討論CPU的流轉過程:

  還是用一個圖來展示:

  從上圖可以看出,系統一上電就開始執行bootloader 當bootloader 執行完以後,把控制權交給了引導程序的head.o 文件裡的start 標號處,當引導程序完成引導工作以後就將控制權轉給真正的內核的head.o 文件裡的start 標號處。這裡就是內核的入口點,最後內核的head.o將控制交給main.o 的start_kernel 函數。這樣,通過查看相應的代碼就可以知道這些代碼到底完成了哪些工作。在這裡我們可以找到相應的代碼,分析一下,看它們到底完成哪些事。下面是我的分析結果:

引導程序: head.o從bootloader接過控制權,並完成如下任務:

    1. 使能 I/D caches ,關閉中斷 , 建立C運行環境(即設置堆棧)由 head.o 和head-xscal.o 完成   

    2. 解壓縮並重定位代碼 ,由misc.o 完成

    3. 其他硬件相關的設置,如big.endian.o 為cpu設置大端模式

內核入口點:從引導程序接過控制權,完成如下任務

    1. 檢查有效的cpu 和cpu的信息

    2. 創建初始化頁表入口

    3. 使能MMU

    4. 檢測錯誤並報告

    5. 跳轉到內核本身 main.c 文件裡的 start_kernel()函數

內核啟動:從kernel 的head.o接過控制權,開始內核的啟動,在這裡完成內核的初始化,如內核各個子系統的初始化。

Copyright © Linux教程網 All Rights Reserved