1. 程式人生 > >【linux】驅動-2-核心模組

【linux】驅動-2-核心模組

[toc] --- ## 前言 * 以野火i.M 6U為例 ## 2. 核心模組 本章節筆記主要理解核心模組程式碼框架和原理,分析一個簡單的核心模組例子。 需要明確的是**模組**和**驅動**是兩回事。 ### 2.1 核心模組概念 #### 2.1.1 核心 核心,是一個作業系統的核心。是基於硬體的第一層軟體擴充,提供作業系統的最基本的功能, 是作業系統工作的基礎,決定著整個作業系統的效能和穩定性。 核心按照體系結構分為:**微核心**和**巨集核心**。 * 參考圖:![](https://img2020.cnblogs.com/blog/2085252/202103/2085252-20210317205514283-1432589303.png) #### 2.1.2 核心模組機制的引入 提高系統靈活性,在除錯驅動的時候不需要重新編譯核心,也不需要重新啟動核心,只需要插入需要除錯的驅動即可。 核心模組的特點: * 模組本身不被編譯入核心映像,這控制了核心的大小。 * 模組一旦被載入,它就和核心中的其它部分完全一樣。 ### 2.2 核心模組 核心模組編譯後會得到一個 **.ko** 的 **ELF** 檔案。(***ELF 檔案可以百度一下,也可以參考野火的核心模組章節***。) **ELF** 檔案:這類檔案包含了程式碼和資料,可以被用來連結成可執行檔案或共享目標檔案,靜態連結庫也可以歸為這一類。 #### 2.2.1 核心模組參考例程 必須內容可分為以下幾點: * **入口函式**:當通過insmod或modprobe命令載入核心模組時,模組的載入函式就會自動被核心執行,完成本模組相關的初始化工作。 * **出口函式**:執行rmmod命令解除安裝模組時,模組解除安裝函式就會自動被核心自動執行,完成相關清理工作。 * **協議**:許可證宣告描述核心模組的許可許可權,如果模組不宣告,模組被載入時,將會有核心被汙染的警告。 非必須內容: * **模組引數**:模組引數是模組被載入時,可以傳值給模組中的引數。 * **模組匯出符號**: 模組可以匯出準備好的變數或函式作為符號,以便其他核心模組呼叫。 * **模組的其他相關資訊**: 可以宣告模組作者等資訊。 **hello_module.c** ```c /** @file hello_module.c * @brief 簡要說明 * @details 詳細說明 * @author lzm * @date 2021-02-21 18:08:07 * @version v1.0 * @copyright Copyright By lizhuming, All Rights Reserved * ********************************************************** * @LOG 修改日誌: ********************************************************** */ #include #include #include // 入口函式:安裝驅動時呼叫的函式 static int __init hello_init(void) { printk(KERN_EMERG "[ KERN_EMERG ] Hello Module Init\n"); printk( "[ default ] Hello Module Init\n"); return 0; } // 出口函式:解除安裝驅動時呼叫的函式 static void __exit hello_exit(void) { printk("[ default ] Hello Module Exit\n"); } module_init(hello_init); module_exit(hello_exit); //MODULE_LICENSE("GPL2"); MODULE_AUTHOR("embedfire "); MODULE_DESCRIPTION("hello world module"); MODULE_ALIAS("test_module"); ``` #### 2.2.2 核心模組命令 **insmod**:插入模組:**`insmod+模組完整路徑`**。 **modprobe**:插入模組,**insmod**具備同樣的功能,同樣可以將模組載入到核心中,除此以外**modprobe**還能檢查模組之間的依賴關係, 並且按照順序載入這些依賴,可以理解為按照順序多次執行**insmod**。 **depmod**:建立模組依賴檔案。**modprobe**是怎麼知道一個給定模組所依賴的其他的模組呢?在這個過程中,**depmod**起到了決定性作用,當執行**modprobe**時, 它會在模組的安裝目錄下搜尋**module.dep**檔案,這是**depmod**建立的模組依賴關係的檔案。 **rmmod**:刪除模組:**`insmod+模組名稱`**。 **lsmod**:檢視所有模組。 **modinfo**:顯示模組中的幾個巨集的定義。如協議、作者等等。 #### 2.2.3 系統自動載入模組 ** 讓系統自動載入模組需要用到命令**depmod和modprobe**。 首先需要將我們想要自動載入的模組統一放到 **/lib/modules/核心版本** 目錄下,核心版本使用 **`uname -r`** 查詢; 其次使用**depmod**建立模組之間的依賴關係,命令 **`depmod -a`** ; 這個時候我們就可以在**modules.dep**中看到模組依賴關係,可以使用如下命令檢視: ```sh cat /lib/modules/核心版本/modules.dep | grep calculation ``` 最後在/etc/modules加上我們自己的模組。 * 注意在該配置檔案中,模組不寫成.ko形式代表該模組與核心緊耦合,有些是系統必須要跟核心緊耦合,比如mm子系統, 一般寫成.ko形式比較好,如果出現錯誤不會導致核心出現panic錯誤,如果整合到核心,出錯了就會出現panic。 然後重啟開發板,使用命令**lsmod**即可檢視我們的模組開機就被載入到核心了。 #### 2.2.4 匯出符號 實際上,符號指的就是核心模組中使用 **EXPORT_SYMBOL** 宣告的函式和變數。當模組被裝入核心後,它所匯出的符號都會記錄在公共核心符號表中。可供給其它模組使用。 匯出方法: * 符號必須在模組檔案的全域性部分匯出,不能在函式中使用。 * \_GPL使得匯出的模組只能被GPL許可的模組使用。 * 編譯我們的模組時,這兩個巨集會被拓展為一個特殊變數的宣告,存放在ELF檔案中。 具體也就是存放在ELF檔案的符號表中: * **st_name**: 是符號名稱在符號名稱字串表中的索引值; * **st_value**: 是符號所在的記憶體地址; * **st_size**: 是符號大小; * **st_info**: 是符號型別和繫結資訊; * **st_shndx**: 表示符號所在section。 ```c EXPORT_SYMBOL(name) EXPORT_SYMBOL_GPL(name) // name為要匯出的標誌 ``` 呼叫方法(*例子*): ```c extern int name; ``` #### 2.2.5 模組引數 **模組引數**:模組引數是模組被載入時,可以傳值給模組中的引數。 Linux核心提供一個巨集來實現模組的引數傳遞: ```c #define module_param(name, type, perm) module_param_named(name, name, type, perm) #define module_param_array(name, type, nump, perm) module_param_array_named(name, name, type, nump, perm) ``` * **name**: 我們定義的變數名; * **type**:引數的型別,目前核心支援的引數型別有byte,short,ushort,int,uint,long,ulong,charp,bool,invbool。其中charp表示的是字元指標,bool是布林型別,其值只能為0或者是1;invbool是反布林型別,其值也是隻能取0或者是1,但是true值表示0,false表示1。變數是char型別時,傳參只能是byte,char * 時只能是charp。 * **perm**:表示的是該檔案的許可權,具體引數值見下表: | 對應使用者 | 字元 | 說明 | | :-: | :-: | :-: | | 當前使用者 | S_IRUSR | 使用者具有讀許可權 | | 當前使用者 | S_IWUSR | 使用者具有寫許可權 | | 當前使用者組 | S_IRGRP | 當前使用者組的其它使用者擁有讀許可權 | | 當前使用者組 | S_IWGRP | 當前使用者組的其它使用者擁有寫許可權 | | 其它使用者 | S_IROTH | 其它使用者具有讀許可權 | | 其它使用者 | S_IWOTH | 其它使用者具有寫許可權 | 模組引數使用示例 模組原始碼: ```c static int nameA=0; module_param(nameA,int,0); static bool nameB=0; module_param(nameB,bool,0644); ``` 載入模組後,會在路徑 **/sys/module/模組名/parameters** 下存在以模組引數為名的檔案。(*注:若檔案許可權為0,則無法檢視該檔案,也不會顯示在該路徑*) ## 參考 * [李柱明部落格園](https://www.cnblogs.com/lizhuming/p/14551899.html) *