日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

轉(zhuǎn)載--Linux 可加載內(nèi)核模塊剖析 - linux內(nèi)核 - 開源linux.巨人的腳步...

 jijo 2009-08-04
轉(zhuǎn)載--Linux 可加載內(nèi)核模塊剖析

LKM 與直接編譯到內(nèi)核或典型程序的元素有根本區(qū)別。典型的程序有一個 main 函數(shù),其中 LKM 包含 entry 和 exit 函數(shù)(在 2.6 版本,您可以任意命名這些函數(shù))。當向內(nèi)核插入模塊時,調(diào)用 entry 函數(shù),從內(nèi)核刪除模塊時則調(diào)用 exit 函數(shù)。因為 entry 和 exit 函數(shù)是用戶定義的,所以存在 module_initmodule_exit 宏,用于定義這些函數(shù)屬于哪種函數(shù)。LKM 還包含一組必要的宏和一組可選的宏,用于定義模塊的許可證、模塊的作者、模塊的描述等等。圖 1 提供了一個非常簡單的 LKM 的視圖。

2.6 版本的 Linux 內(nèi)核提供了一個新的更簡單的方法,用于構(gòu)建 LKM。構(gòu)建 LKM 時,可以使用典型的用戶工具管理模塊(盡管內(nèi)部已經(jīng)改變):標準 insmod(安裝 LKM),rmmod (刪除 LKM),modprobeinsmodrmmod 的包裝器),depmod(用于創(chuàng)建模塊依賴項),以及 modinfo(用于為模塊宏查找值)。



剖析內(nèi)核模塊對象

LKM 只不過是一個特殊的可執(zhí)行可鏈接格式(Executable and Linkable Format,ELF)對象文件。通常,必須鏈接對象文件才能在可執(zhí)行文件中解析它們的符號和結(jié)果。由于必須將 LKM 加載到內(nèi)核后 LKM 才能解析符號,所以 LKM 仍然是一個 ELF 對象。您可以在 LKM 上使用標準對象工具(在 2.6 版本中,內(nèi)核對象帶有后綴 .ko,)。例如,如果在 LKM 上使用 objdump 實用工具,您將發(fā)現(xiàn)一些熟悉的區(qū)段(section),比如 .text(說明)、.data(已初始化數(shù)據(jù))和 .bss(塊開始符號或未初始化數(shù)據(jù))。

您還可以在模塊中找到其他支持動態(tài)特性的區(qū)段。.init.text 區(qū)段包含 module_init 代碼,.exit.text 區(qū)段包含 module_exit 代碼(參見圖 2)。.modinfo 區(qū)段包含各種表示模塊許可證、作者和描述等的宏文本。

了解 LKM 的基礎知識之后,現(xiàn)在我們進一步探索模塊是如何進入內(nèi)核的,以及在內(nèi)核內(nèi)部是如何管理模塊的。







LKM 的生命周期

在用戶空間中,insmod(插入模塊)啟動模塊加載過程。insmod 命令定義需要加載的模塊,并調(diào)用 init_module 用戶空間系統(tǒng)調(diào)用,開始加載過程。2.6 版本內(nèi)核的 insmod 命令經(jīng)過修改后變得非常簡單(70 行代碼),可以在內(nèi)核中執(zhí)行更多工作。insmod 并不進行所有必要的符號解析(處理 kerneld),它只是通過 init_module 函數(shù)將模塊二進制文件復制到內(nèi)核,然后由內(nèi)核完成剩余的任務。

init_module 函數(shù)通過系統(tǒng)調(diào)用層,進入內(nèi)核到達內(nèi)核函數(shù) sys_init_module(參見圖 3)。這是加載模塊的主要函數(shù),它利用許多其他函數(shù)完成困難的工作。類似地,rmmod 命令會使 delete_module 執(zhí)行 system call 調(diào)用,而 delete_module 最終會進入內(nèi)核,并調(diào)用 sys_delete_module 將模塊從內(nèi)核刪除。

在模塊的加載和卸載期間,模塊子系統(tǒng)維護了一組簡單的狀態(tài)變量,用于表示模塊的操作。加載模塊時,狀態(tài)為 MODULE_STATE_COMING。如果模塊已經(jīng)加載并且可用,狀態(tài)為 MODULE_STATE_LIVE。此外,卸載模塊時,狀態(tài)為 MODULE_STATE_GOING。







模塊加載細節(jié)

現(xiàn)在,我們看看加載模塊時的內(nèi)部函數(shù)(參見圖 4)。當調(diào)用內(nèi)核函數(shù) sys_init_module 時,會開始一個許可檢查,查明調(diào)用者是否有權(quán)執(zhí)行這個操作(通過 capable 函數(shù)完成)。然后,調(diào)用 load_module 函數(shù),這個函數(shù)負責將模塊加載到內(nèi)核并執(zhí)行必要的調(diào)試(后面還會討論這點)。load_module 函數(shù)返回一個指向最新加載模塊的模塊引用。這個模塊加載到系統(tǒng)內(nèi)具有雙重鏈接的所有模塊的列表上,并且通過 notifier 列表通知正在等待模塊狀態(tài)改變的線程。最后,調(diào)用模塊的 init() 函數(shù),更新模塊狀態(tài),表明模塊已經(jīng)加載并且可用。

加載模塊的內(nèi)部細節(jié)是 ELF 模塊解析和操作。load_module 函數(shù)(位于 ./linux/kernel/module.c)首先分配一塊用于容納整個 ELF 模塊的臨時內(nèi)存。然后,通過 copy_from_user 函數(shù)將 ELF 模塊從用戶空間讀入到臨時內(nèi)存。作為一個 ELF 對象,這個文件的結(jié)構(gòu)非常獨特,易于解析和驗證。

下一步是對加載的 ELF 映像執(zhí)行一組健康檢查(它是有效的 ELF 文件嗎?它適合當前的架構(gòu)嗎?等等)。完成健康檢查后,就會解析 ELF 映像,然后會為每個區(qū)段頭創(chuàng)建一組方便變量,簡化隨后的訪問。因為 ELF 對象的偏移量是基于 0 的(除非重新分配),所以這些方便變量將相對偏移量包含到臨時內(nèi)存塊中。在創(chuàng)建方便變量的過程中還會驗證 ELF 區(qū)段頭,確保加載的是有效模塊。

任何可選的模塊參數(shù)都從用戶空間加載到另一個已分配的內(nèi)核內(nèi)存塊(第 4 步),并且更新模塊狀態(tài),表明模塊已加載(MODULE_STATE_COMING)。如果需要 per-CPU 數(shù)據(jù)(這在檢查區(qū)段頭時確定),那么就分配

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多