本文主要講述嵌入式Linux啟動時間優(yōu)化的秘密之三-內(nèi)核,我們繼續(xù)上篇沒有講完的嵌入式Linux啟動時間優(yōu)化方法,本文主要會講內(nèi)核系統(tǒng)。想看上一篇的請查看本文結(jié)尾的鏈接。
內(nèi)核
1.有用的調(diào)試手段
1. 1 內(nèi)核初始化度量函數(shù)
要找出最長執(zhí)行時間的內(nèi)核初始化函數(shù),請在內(nèi)核命令行中添加initcall_debug。將內(nèi)核日志中得到如下日志:
如使用initcall_debug可能需要在內(nèi)核配置中使用CONFIG_LOG_BUF_SHIFT增加日志緩沖區(qū)的大小。還可能需要使能CONFIG_PRINTK_TIME和CONFIG_KALLSYMS。
1.2 使用內(nèi)核啟動圖進(jìn)行有目的的優(yōu)化
使用initcall_debug可以生成啟動圖,從而輕松查看哪些內(nèi)核初始化函數(shù)需要最多時間來執(zhí)行。
復(fù)制dmesg命令的輸出并將其粘貼到文件中(我們將其稱為啟動日志boot.log)
在開發(fā)工作站上,在內(nèi)核源代碼中運(yùn)行scripts / bootgraph.pl腳本:scripts / bootgraph.pl boot.log》 boot.svg
現(xiàn)在可以使用矢量圖形編輯器(例如inkscape)打開啟動圖:
首先從花費(fèi)最長時間的功能開始嘗試優(yōu)化。對于每個功能:
在內(nèi)核源代碼中查找其定義。
可以使用Elixir(參考https://elixir.bootlin.com)。
注意:某些函數(shù)名稱可能不存在,名稱與modulename_init相對應(yīng)。然后,在相應(yīng)的模塊中查找初始化代碼。
刪除不必要的功能:
通過查看相應(yīng)源目錄中的Makefile,找到哪個內(nèi)核配置參數(shù)可編譯代碼。
延后加載處理:
查找功能所屬的模塊(如果有)。如果可能,請稍后加載此模塊。
優(yōu)化必要的功能:
查找可以用于減少探測時間的參數(shù),并查找module_param宏。
查找延遲循環(huán)和對名稱中包含delay的函數(shù)的調(diào)用, 可以減少此類延遲,并查看代碼是否仍然有效。
1.3 減小內(nèi)核尺寸
首先,我們專注于在不刪除功能的情況下縮小尺寸
主要機(jī)制是使用內(nèi)核模塊
將啟動時不需要的所有內(nèi)容編譯為模塊
有兩個好處:內(nèi)核更小且加載速度更快,初始化代碼更少
刪除用戶空間不需要的功能:
CONFIG_KALLSYMS,CONFIG_DEBUG_FS,CONFIG_BUG
用專為嵌入式系統(tǒng)設(shè)計的功能:CONFIG_SLOB,CONFIG_EMBEDDED
然后考慮內(nèi)核壓縮的方式:
根據(jù)存儲讀取速度和CPU解壓縮內(nèi)核之間的平衡,需要對不同的壓縮算法進(jìn)行測試。還建議在內(nèi)核優(yōu)化過程結(jié)束時嘗試壓縮選項(xiàng),因?yàn)榻Y(jié)果可能會因內(nèi)核大小而異。
Lzo和Gzip似乎是最好的解決方案。 但這結(jié)果取決于存儲和CPU性能,故在決定方案是務(wù)必進(jìn)行測試。
另外內(nèi)核的編譯選項(xiàng)也有可以優(yōu)化的可能:
CONFIG_CC_OPTIMIZE_FOR_SIZE:可以使用gcc -Os而不是gcc -O2編譯內(nèi)核。
這樣的優(yōu)化會優(yōu)先考慮代碼大小,但會犧牲代碼速度。
結(jié)果:初始引導(dǎo)時間更好(較小的啟動時間),但是較慢的內(nèi)核代碼可能會使性能降低。系統(tǒng)運(yùn)行速度會變慢!
1.4 延遲驅(qū)動程序和初始化調(diào)用
如果有點(diǎn)功能無法編譯為模塊(例如,網(wǎng)絡(luò)或模塊子系統(tǒng)),可以嘗試推遲執(zhí)行。內(nèi)核不會縮小,但某些初始化將被推遲,所以啟動變快。通常,您可以修改probe()函數(shù)以返回-EPROBE_DEFER,直到它們準(zhǔn)備好運(yùn)行為止。
有關(guān)支持此功能的詳細(xì)信息,請參見
https://lwn.net/Articles/485194/。
1.5 關(guān)閉控制臺輸出
控制臺輸出實(shí)際上要花費(fèi)很多時間(非常慢的設(shè)備)。 產(chǎn)品中可能不需要。通過在內(nèi)核命令行中傳遞quiet參數(shù)來禁用它。但仍然可以使用dmesg獲取內(nèi)核消息。這一步一般建議等最后一步再做,否則將損失控制臺進(jìn)行調(diào)試。
1.6 預(yù)置jiffy
每次引導(dǎo)時,Linux內(nèi)核都會校準(zhǔn)延遲循環(huán)(用于udelay()函數(shù))。這將測量每個jiff y(lpj)值的循環(huán)次數(shù)。只需要測量一次!在內(nèi)核啟動消息中找到 lpj值:
Calibrating delay loop.。。 996.14 BogoMIPS (lpj=4980736)
然后將lpj = 《value》添加到內(nèi)核命令行:
Calibrating delay loop (skipped) preset value.。 996.14 BogoMIPS (lpj=4980736)
1.7 多處理器
SMP初始化很慢,即使您只有一個核心CPU,通常也會在默認(rèn)配置中啟用它(默認(rèn)配置應(yīng)支持多個系統(tǒng))。因此,如果只有一個CPU內(nèi)核,請確保將其禁用。BeagleBone Black上的結(jié)果:壓縮內(nèi)核大?。?188 KB
要節(jié)省最后的毫秒數(shù),您可能需要刪除不必要的功能:
CONFIG_PRINTK = n與quiet命令行參數(shù)具有相同的效果,但是您無權(quán)訪問內(nèi)核消息。但是,您將擁有一個非常小的內(nèi)核。
在Thumb2模式下編譯內(nèi)核:CONFIG_THUMB2_KERNEL(任何ARM工具鏈都可以做到)。
模塊裝卸
塊層(Block layer)
網(wǎng)絡(luò)堆棧
USB堆棧
電源管理功能
CONFIG_SYSFS_DEPRECATED
輸入:鍵盤/鼠標(biāo)/觸摸屏
減少CONFIG_LEGACY_PTY_COUNT的值或設(shè)置pty.legacy_count內(nèi)核參數(shù).
評論