系統啓動 之 Linux系統啓動概述(1)

        隨着智能終端功能的愈來愈龐大,與之,硬件配置愈來愈高,開機時間卻愈來愈長。人們在享受強大功能的同時,對冗長的智能終端的開機時間卻愈來愈缺少耐心。
爲了「取悅」用戶,須要提供較好的用戶體驗,那麼就必須使得智能終端儘量短的進入「可工做」狀態。
       本文中的「儘量短的開機時間」,「開機優化」、「開機時間優化」均表示同一個意思。
       若是計劃對linux系統進行開機時間優化,那麼就必須熟悉linux啓動流程,本小節主要從框架上對Linux啓動作簡單的介紹,並不會詳細的描述。
       以下圖:
linux


       須要明確的是preloader、lk(Little Kernel)、kernel、android這些系統鏡像文件是存儲在nand flash中的,而後每一個芯片都有個boot rom,在上電時刻,boot rom開始啓動,boot rom加載preloader到內部SRAM中,preloader被加載完成以後,程序就從boot rom跳轉到preloader處開始執行,preloader初始化好外部RAM以後,preloader將lk(或uboot)加載外部RAM中,而後跳轉到lk(或uboot)中去執行,lk(或uboot)緊接着就加載bootimage(包括kernel和ramdisk)到外部RAM中,而後去執行kernel部分。


android

1.1BootRom

       ROM code是芯片廠商直接燒寫到芯片中。
(1)  設備上電後,Boot ROM開始運行。
(2)  BootROM初始化軟件堆棧(software stack)、通訊端口和可引導存儲設備(好比NAND/EMMC)。
(3)  BootROM經過UART/USB和flash工具握手。
(4)  BootROM經過UART下載pre-loader鏡像到NANDflash/EMMC中,而後重啓。
(5)  BootROM加載pre-loader到內部SRAM彙總,由於DRAM尚未初始化。
(6)  BootROM跳轉到pre-loader並執行。

shell

1.2 BootLoader

       BootLoader程序也有多種類型,不一樣的BootLoader程序,其引腳參數不一樣。

       
(1) SD方式
(2) NorFlash Rom方式
(3) NandFlash Rom + chip方式
       通常狀況下,發佈的正式版本,引腳參數都是固定的,是不可改變的。
緩存

 

1.2.1 preLoader

       preloader也就是BootLoader的第一部分。
       pre-loader是內置的loader,它的主要功能以下:
(1)  負責在芯片組平臺(chipset platform)上準備好可執行的環境
(2)  若是外部工具備效,它會試圖經過UART或是USB來和外部工具握手。(好比USB升級)
(3)  從NAND/EMMC加載U-Boot,並跳轉到U-Boot。
(4)  使用工具握手,設備可以觸發進入下載模式來下載須要的鏡像,或是進入工廠/測試模式,好比META模式和ATE工廠模式,在這些模式下能夠測試模塊,或是經過傳遞引導參數給U-Boot和linux內核來校準設備(devicecalibration)


1.2.2 U-Boot

       U-Boot也就是BootLoader的第二部分。
 
1) 初始化本階段使用的硬件設備
2) 檢測系統內存映射
3) 將內核從Flash讀取到RAM中
4) 爲內核設置啓動參數
       U-Boot在執行過程當中必須設置和初始化 Linux 的內核啓動參數。Linux內核在啓動過程當中會根據該啓動參數進行相應的初始化工做。
5) 調用內核映像
       U-Boot完成的最後一項工做即是調用 Linux內核。若是 Linux 內核存放在 Flash 中,而且可直接在上面運行(這裏的 Flash指 Nor Flash),那麼可直接跳轉到內核中去執行。但因爲在 Flash 中執行代碼會有種種限制,並且速度也遠不及 RAM 快,因此通常的嵌入式系統都是將 Linux內核拷貝到 RAM 中,而後跳轉到 RAM 中去執行。不論哪一種狀況,在跳到 Linux 內核執行以前 CUP的寄存器必須知足如下條件:r0=0,r1=處理器類型,r2=標記列表在 RAM中的地址。
智能終端在該階段可能作了更多動做。
 

1.3 kernel

       start_kernel是全部 Linux 平臺進入系統內核初始化後的入口函數,它主要完成剩餘的與硬件平臺相關的初始化工做,在進行一系列與內核相關的初始化後,調用第一個用戶進程-init 進程並等待用戶進程的執行,這樣整個 Linux 內核便啓動完畢。該函數所作的具體工做有:
       1) 調用 setup_arch()函數進行與體系結構相關的第一個初始化工做;
對不一樣的體系結構來講該函數有不一樣的定義。對於 ARM 平臺而言,該函數定義在arch/arm/kernel/Setup.c。它首先經過檢測出來的處理器類型進行處理器內核的初始化,而後經過 bootmem_init()函數根據系統定義的 meminfo 結構進行內存結構的初始化,最後調用paging_init()開啓 MMU,建立內核頁表,映射全部的物理內存和 IO空間。
       2) 建立異常向量表和初始化中斷處理函數;
       3) 初始化系統核心進程調度器和時鐘中斷處理機制;
       4) 初始化串口控制檯(serial-console);
ARM-Linux 在初始化過程當中通常都會初始化一個串口作爲內核的控制檯,這樣內核在啓動過程當中就能夠經過串口輸出信息以便開發者或用戶瞭解系統的啓動進程。
       5) 建立和初始化系統 cache,爲各類內存調用機制提供緩存,包括;動態內存分配,虛擬文件系統(VirtualFile System)及頁緩存。
       6) 初始化內存管理,檢測內存大小及被內核佔用的內存狀況;
       7) 初始化系統的進程間通訊機制(IPC);
       當以上全部的初始化工做結束後,start_kernel()函數會調用 rest_init()函數來進行最後的初始化,包括建立系統的第一個進程-init 進程來結束內核的啓動。Init 進程首先進行一系列的硬件初始化,而後經過命令行傳遞過來的參數掛載根文件系統。最後init 進程會執行用 戶傳遞過來的「init=」啓動參數執行用戶指定的命令,或者執行如下幾個進程之一:
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)。
       當全部的初始化工做結束後,cpu_idle()函數會被調用來使系統處於閒置(idle)狀態並等待用戶程序的執行。至此,整個 Linux 內核啓動完畢。


1.4 Init

       init命令是Linux下的進程初始化工具,init進程是全部Linux進程的父進程,它的進程號爲1。init命令是Linux操做系統中不可缺乏的程序之一,init進程是Linux內核引導運行的,是系統中的第一個進程。

1.4.1 /etc/inittab

       做爲系統的第一個執行的程序「/sbin/init」。init程序作的工做至關多,除了利用設置文件「/etc/inittab」來獲取運行等級以外,還會經過運行等級的設置值啓動不一樣的服務項目。運行等級是指linux經過設置不一樣等級來規定系統用不一樣的服務來啓動,讓linux的使用環境不一樣。

       "/etc/inittab"中有這麼一句" si::sysinit:/etc/init.d/rcS",代表系統須要主動使用"rcS"這個shell腳原本設置系統環境。但這個文件的文件名在各個版本中基本上都是有區別的。
網絡

# /etc/inittab: init(8)configuration.
# $Id: inittab,v 1.91 2002/01/2513:35:21 miquels Exp $
 
# The default runlevel.
id:3:initdefault:
 
1:012345:respawn:/sbin/getty -n -LttyMT0 115200 vt100 -l /bin/sh
 
# Boot-time systemconfiguration/initialization script.
# This is run first except whenbooting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS


1.4.2 rcS

1.  source/etc/profile
2.  掛載 fstab 基本的文件系統 (/, proc, sys, devpts, tmpfs…)
3.  而後轉 rc.local
#! /bin/sh
#設置環境變量
source /etc/profile
 
# Don't use scripts. Just use mount-a for fast boot.
/bin/mount-avt nonfs,nosmbfs
 
#if [ -e /etc/readahead_early ];then
#   echo Start readahead /etc/readahead_early
#   busybox readahead `cat /etc/readahead_early` &
#fi
 
#      Run /etc/rc.d/rc.local if it exists
[ -x /etc/rc.d/rc.local ] &&/etc/rc.d/rc.local


1.4.3 用戶自定義引導程序(/etc/rc.d/rc.local)

       通常來講,自定義的程序不須要執行上面所說的繁瑣的創建shell增長連接文件的步驟,只須要將命令放在rc.local裏面就能夠了,這個shell腳本就是保留給用戶自定義啓動內容的。
1.  設置終端參數 stty
2.  設置基本網絡相關參數 (lo, hosts, resolv.conf, …)

......框架

相關文章
相關標籤/搜索