嵌入式Linux系統主要特點在于使用Bootloader替代了桌面系統的BIOS,同時對系統進行了規模上的裁剪,但硬件上的劣勢往往導致系統啟動速度較慢,而嵌入式產品使用者又對系統的開機速度比較敏感,樣就產生了對于提高嵌入式Linux系統啟動速度的需求。本文對系統啟動時執行哪些階段的操作CONTROL ENGINEERING China版權所有,以及縮短這些操作時間的方法進行了探討。
1 嵌入式Linux系統啟動時序
目前,嵌入式系統的硬件平臺和應用方向區別很大,但總體啟動流程一致的。這里的系統啟動是指從用戶執行上電/復位操作,到系統開始提供用戶可接收的服務水平所需要的過程。典型的上電/復位時序如表1所列。
表1 嵌入式Linux系統啟動時序
2 Linux快速啟動方法
目前,一些Linux的發行版本已經對啟動速度進行了優化。如果利用標準Linux進行開發,則啟動速度的提高主要是通過內核配置和各種補丁包來實現的。下面分析快速啟動的一些關鍵技術。
2.1 Firmware和Bootloader階段
目標板一旦確定,Firmware運行的時間就無法改變了,Flash和RAM的讀寫速度也就隨之確定了。但如果復位時能夠繞過Firmware和Bootloader,即允許運行中的內核加載以及運行另一個內核,可以縮短啟動的時間。典型的實現有Kexec,它有2個組件,即用戶空間組件kexectools和內核補丁。另外一種辦法是在內核命令行中加入reboot=soft數www.cechina.cn,同樣可以跳過Firmware,但是缺點在于無法從用戶空間調用。
對于正常啟動,可以選擇速度比較快的Bootloader,并對內核進行小型化處理;還可以使用高速的映像復制技術(如DMA2RAM),從而縮短復制的時間。為了縮短解壓消耗的時間,可尋求比較高效的壓縮算法。但一般情況下,壓縮比越高,算法越復雜,解壓速度就越慢,從而造成復制時間(與壓縮比成反比)和解壓時間(一般與壓縮比成正比)之間的矛盾。
2.2 內核階段
內核初始化時要對RealTime Clock (RTC)進行同步。此過程要占用1s的時間www.cechina.cn,可去掉以節約時間,但這樣CPU會與正確的時間有1s的偏差,如果關機時CPU時鐘又要保存在RTC中,偏差就會不斷累積。但對于使用外部時鐘源進行同步的系統,則可安全地跳過這個階段。
Preset LPJ可以用來縮短每次啟動時調用calibrate_delay()來校準loops_per_jiffy消耗的時間。這個時間開銷與CPU頻率無關,在典型的嵌入式硬件環境下會消耗300ms左右。LPJ值對于固定硬件平臺應該是一致的,可以只計算一次,在后續的啟動中就可以在啟動參數中強制指定LPJ值,而跳過實際的計算過程。具體方法是:在正常啟動后記錄下內核啟動信息中的"Calibrating Delay"數值,在啟動參數中以"lpj=xxxxxx"的形式強制指定。
啟動過程默認打開控制臺輸出啟動消息,但是控制臺尤其是基于幀緩沖的控制臺會減慢啟動速度。因此在嵌入式Linux產品中,將啟動過程中的控制臺設為靜默狀態,方法是在內核啟動參數中加入"quiet"。
設備搜索和驅動安裝是比較耗時的操作,因此要在編譯內核時確定需要安裝哪些驅動模塊,以免系統搜索那些根本不存在的設備,尤其是多余的IDE設備。對于啟動時暫時不用安裝的設備,盡量將驅動編譯成模塊,在以后空閑時或者使用設備時加載,而不是全部放在啟動階段。
2.3 用戶空間階段
傳統Linux的初始化腳本是由bash執行的,在內核引導后啟動init進程(/sbin/init)。它使用一個ASCII文件(/etc/inittab)來改變運行級別控制工程網版權所有,這個文件中又會調用RCSript,由RCSript查找/etc/rc.d/rc5.d/并啟動相應鏈接指向的系統服務。
消費電子類Linux系統需要啟用圖形界面等必要的服務,未經優化的系統在這個過程中會默認啟動很多根本用不到或者當前用不到的系統服務,這一部分會花去較大的時間開銷。最簡單的優化辦法就是根據實際需要,通過改寫服務配置文件定制系統服務。另外控制工程網版權所有,init腳本的執行是串行的,在腳本量大時會導致引導過程非常,因此可以考慮并行運行各種服務以加快啟動的速度。現在已經出現了一些初始化程序來替代init進程,下面介紹initng和upstart。
initng(init nextgerneration)能夠并行啟動服務從而快速完成初始化工作。initng認為滿足了依賴關系的服務就可以啟動。在從外存加載一個腳本或等待硬件設備啟動的同時,可以運行另一個腳本來啟動別的服務,使系統在CPU 和 I/O 之間實現較好的平衡。作為一個基于依賴關系的解決方案,initng使用自己的初始化腳本集,它