歡迎關注“嵌入式分享”,每周更新!? 正文
從接觸 Linux 系統開始,我們就知道內核內置(built-in)驅動會在系統上電啟動時自動加載,而編譯為.ko文件的驅動則需要手動通過insmod加載。
這看似順理成章的差異,背后實則是內核對驅動初始化機制的精巧設計 —— 核心在于module_init和module_exit這兩個宏在不同編譯模式下的實現邏輯差異。
要理解這一點,首先需要明確一個前提:無論是內置驅動還是可加載模塊,其初始化和卸載的核心邏輯都是通過module_init(入口)和module_exit(出口)定義的。兩者的差異并非 “是否執行這些函數”,而是 “何時、如何觸發這些函數的執行”。
有了以上思路,問題就好辦了。
先從module_init/module_exit 入手,閱讀源碼(源碼路徑:include/linux/module.h)知道,這兩個宏根據驅動是否編譯為模塊,會展開為不同的代碼,從而決定初始化函數的調用時機。
當驅動為內置模塊(#ifndefMODULE)
此時MODULE宏未定義,module_init被定義為__initcall(x):

__initcall(x):將函數x注冊到內核的初始化調用隊列中。內核啟動時,會按優先級依次執行所有__initcall標記的函數(從early_initcall到late_initcall)。
編譯時,這些初始化函數會被歸類到內核的初始化段(如.init.text),內核啟動時會按順序執行這些函數。
因此,內置驅動的初始化函數會在系統啟動階段自動執行,無需手動干預。
當驅動為可加載模塊
此時MODULE宏被定義(編譯時通過-DMODULE指定),module_init和module_exit的定義完全不同。
module_init(initfn):將用戶定義的initfn函數別名為init_module(內核模塊加載器約定的初始化入口)。 module_exit(exitfn):將用戶定義的exitfn函數別名為cleanup_module(模塊卸載時的入口)。
當通過insmod加載.ko文件時,內核會調用init_module函數;通過rmmod卸載時,會調用cleanup_module函數。這兩個函數與用戶定義的initfn/exitfn是同一個函數(通過alias屬性關聯)。
總結
內置驅動與可加載模塊的加載差異,本質是module_init宏在不同編譯模式下的實現分流:
可加載模塊通過 “函數別名” 將初始化邏輯綁定到insmod觸發的標準入口,屬于 “用戶態手動觸發”;
內置驅動通過 “初始化調用鏈” 將初始化邏輯注冊到內核啟動流程,屬于 “內核態自動執行”。
這種設計既保證了系統關鍵驅動的自動初始化(確保啟動流程順暢),又提供了非關鍵驅動的動態加載能力(提升靈活性、節省內存),是 Linux 內核設備模型 “模塊化” 與 “啟動可靠性” 的精妙平衡。
(完)
本人專注 Linux 驅動 & Linux/Android BSP 開發調試,可接外包項目/技術支持/問題定位。有需求可加微信:【Chen_WeChat2026】。
更多原創技術文章:《README 2026》
審核編輯 黃宇
-
Linux
+關注
關注
88文章
11758瀏覽量
219008 -
Kernel
+關注
關注
0文章
50瀏覽量
12076
發布評論請先 登錄
嵌入式驅動開發,需要掌握哪些技能?
什么是嵌入式應用開發?
ARM嵌入式這樣學
嵌入式硬件設計解析
嵌入式需要掌握哪些核心技能?
Melexis推出新型嵌入式電機驅動芯片MLX81339
嵌入式從入門到進階,怎么學?
Linux嵌入式和單片機嵌入式的區別?
運行在嵌入式系統上的emApps
【RK3588】嵌入式人工智能實驗箱——智啟高校產教融合新平臺
嵌入式開發入門指南:從零開始學習嵌入式
飛凌嵌入式2025嵌入式及邊緣AI技術論壇圓滿結束
飛凌嵌入式「2025嵌入式及邊緣AI技術論壇」議程公布
嵌入式分享#57:為什么 Kernel 內置驅動能 “上電自啟”?
評論