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