1.內核模塊對象
LKM 只不過是一個特殊的可執行可鏈接格式(Executable and Linkable Format,ELF)對象文件。通常,必須鏈接對象文件才能在可執行文件中解析它們的符號和結果。由於必須將 LKM 加載到內核後 LKM 才能解析符號,所以 LKM 仍然是一個 ELF 對象。您可以在
LKM 上使用標準對象工具(在 2.6 版本中,內核對象帶有後綴 .ko,)。例如,如果在 LKM 上使用 objdump
實用工具,您將發現一些熟悉的區段(section),比如.text(說明)、.data(已初始化數據)和 .bss(塊開始符號或未初始化數據)。
圖 2. 具有各種 ELF 區段的 LKM 的示例
2.LKM的生命週期
- 在用戶空間中,
insmod
(插入模塊)啓動模塊加載過程。 insmod
命令定義需要加載的模塊,並調用 init_module
用戶空間系統調用,開始加載過程。2.6
版本內核的 insmod
命令經過修改後變得非常簡單(70
行代碼),可以在內核中執行更多工作。insmod
並不進行所有必要的符號解析(處理 kerneld
),它只是通過 init_module
函數將模塊二進制文件複製到內核,然後由內核完成剩餘的任務。init_module
函數通過系統調用層,進入內核到達內核函數 sys_init_module
(參見圖
3)。這是加載模塊的主要函數,它利用許多其他函數完成困難的工作。
圖 3. 加載和卸載模塊時用到的主要命令和函數
類似地,rmmod
命令會使 delete_module
執行 system
call
調用,而 delete_module
最終會進入內核,並調用sys_delete_module
將模塊從內核刪除。
現在,我們看看加載模塊時的內部函數(參見圖 4)。
- 當調用內核函數
sys_init_module
時,會開始一個許可檢查,查明調用者是否有權執行這個操作(通過 capable
函數完成)。 - 然後,調用
load_module
函數,這個函數負責將模塊加載到內核並執行必要的調試(後面還會討論這點)。load_module
函數返回一個指向最新加載模塊的模塊引用。這個模塊加載到系統內具有雙重鏈接的所有模塊的列表上,並且通過
notifier 列表通知正在等待模塊狀態改變的線程。 - 最後,調用模塊的
init()
函數,更新模塊狀態,表明模塊已經加載並且可用。
圖 4. 內部(簡化的)模塊加載過程