先看幾道題,自測看看是否需要閱讀本篇文章。
Q1. 上電后 DRAM 尚未初始化時,通常由誰運行?
A. 完整 U-Boot(在 DDR 中)
B. BootROM / SPL(片內 SRAM 路徑)
C. Linux 內核早期解壓代碼
D. systemd 的 generator
答案:B。早期只能在 SRAM/ROM 路徑,SPL 負責把 DDR 拉起來再加載 U-Boot proper。
Q2. U-Boot 與 Linux 內核之間,最核心的「硬件描述」契約是?
A. /etc/fstab
B. systemd target
C. Device Tree Blob (DTB) + bootargs
D. glibc ABI
答案:C。DTB 描述板級硬件,bootargs 傳遞 root/console 等運行參數。
Q3. 「業務上電后要延遲 5 秒再連云」這類策略,優先放在哪一層?
A. 用戶態服務 / 應用(如 systemd timer 或業務邏輯)
B. 內核調度器源碼
C. BootROM
D. 設備樹 clock 節點
答案:A。產品策略應留在用戶態,便于迭代且不影響內核穩定性。
Q4. 串口停在 “Starting kernel …” 之后沒有繼續,優先懷疑?
A. systemd 某個 unit 掛了
B. 應用層 segfault
C. D-Bus 未啟動
D. 內核早期啟動 / 控制臺 / DTB 或解壓跳轉問題
答案:D。此時 PID 1 尚未運行,應查內核早期與 U-Boot 交接(地址、DTB、console)。
嵌入式Linux從來不是“一個大程序”,而是一條多階段接力的啟動鏈,加上運行期穩定存在的內核空間 + 用戶空間。

這張圖有兩個時間維度,千萬不要混為一談:
BootROM固化在i.MX6ULL硅片里,出廠即定。它根據啟動引腳/熔絲選擇啟動介質(SD、eMMC、NAND、USB下載等),把第一級可執行鏡像載入片內SRAM。
我們不需要動它,但必須知道它的存在。
為什么要分SPL和完整U-Boot?因為上電瞬間DRAM還不可用,完整U-Boot放不進片內SRAM。
這一層的核心職責是準備“可啟動的內存布局”:
bootargs(內核命令行)
bootargs是U-Boot傳給Linux的命令行字符串,典型內容如console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait。它是啟動層與內核層之間的重要契約。
內核我們先記住四大塊就夠用了:

內核不該塞業務策略(比如“三次重試后彈窗提示用戶”)。那是用戶態的事。內核只做三件事:接口穩定、資源安全、策略可配置。
根文件系統是內核mount成功后的完整世界:動態庫、配置、/dev、/etc、服務單元、應用二進制。
沒有可用的rootfs,內核會直接panic——經典報錯:
VFS: Unable to mount root fs on unknown-block(0,0)
Rootfs可由eMMC/SD分區、NFS、initramfs等承載。Buildroot/Yocto的核心產物之一就是它。
內核啟動的第一個用戶進程是PID 1,也就是init。
我們接觸的systemd就是init的一種實現:它負責服務依賴圖、日志、目標運行態。在它之上,才是我們的采集、UI、云連接、OTA等業務進程。
PID 1如果退出,內核通常會panic或觸發重啟策略。它比普通進程“高貴”得多。
架構清晰,往往因為接口比實現更穩定。記住四條跨層契約:

工作落地一句話:改需求時先問“我改的是哪條契約的哪一側?”
改契約本身(比如換root設備命名、改DTB兼容字符串)比改內部實現更危險,必須回歸啟動與量產流程。
printenv,找bootargs、bootcmd、fdt_file/fdtfile、loadaddr0x80800000,DTB ≈ 0x83000000bootz ${loadaddr} - ${fdt_addr}(中間的-表示無initramfs)cat /proc/cmdline —— 看到U-Boot傳入的bootargsls /sys/firmware/devicetree/base —— 查看運行中的設備樹ps -p 1 -o comm= —— 確認PID 1是systemd還是其他systemctl status —— 看服務依賴圖
END
作者:LinuxZn