目錄
- 前言
- 2. 核心子產品
- 2.1 核心子產品概念
- 2.1.1 核心
- 2.1.2 核心子產品機制的引入
- 2.2 核心子產品
- 2.2.1 核心子產品參考例程
- 2.2.2 核心子產品指令
- 2.2.3 系統自動加載子產品 **
- 2.2.4 導出符号
- 2.2.5 子產品參數
- 2.1 核心子產品概念
- 參考
- 以野火i.M 6U為例
本章節筆記主要了解核心子產品代碼架構和原理,分析一個簡單的核心子產品例子。
需要明确的是子產品和驅動是兩回事。
核心,是一個作業系統的核心。是基于硬體的第一層軟體擴充,提供作業系統的最基本的功能, 是作業系統工作的基礎,決定着整個作業系統的性能和穩定性。
核心按照體系結構分為:微核心和宏核心。
- 參考圖:
提高系統靈活性,在調試驅動的時候不需要重新編譯核心,也不需要重新啟動核心,隻需要插入需要調試的驅動即可。
核心子產品的特點:
- 子產品本身不被編譯入核心映像,這控制了核心的大小。
- 子產品一旦被加載,它就和核心中的其它部分完全一樣。
核心子產品編譯後會得到一個 .ko 的 ELF 檔案。(ELF 檔案可以百度一下,也可以參考野火的核心子產品章節。)
ELF 檔案:這類檔案包含了代碼和資料,可以被用來連結成可執行檔案或共享目标檔案,靜态連結庫也可以歸為這一類。
必須内容可分為以下幾點:
- 入口函數:當通過insmod或modprobe指令加載核心子產品時,子產品的加載函數就會自動被核心執行,完成本子產品相關的初始化工作。
- 出口函數:執行rmmod指令解除安裝子產品時,子產品解除安裝函數就會自動被核心自動執行,完成相關清理工作。
- 協定:許可證聲明描述核心子產品的許可權限,如果子產品不聲明,子產品被加載時,将會有核心被污染的警告。
非必須内容:
- 子產品參數:子產品參數是子產品被加載時,可以傳值給子產品中的參數。
- 子產品導出符号: 子產品可以導出準備好的變量或函數作為符号,以便其他核心子產品調用。
- 子產品的其他相關資訊: 可以聲明子產品作者等資訊。
hello_module.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 <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
// 入口函數:安裝驅動時調用的函數
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");
insmod:插入子產品:
insmod+子產品完整路徑
。
modprobe:插入子產品,insmod具備同樣的功能,同樣可以将子產品加載到核心中,除此以外modprobe還能檢查子產品之間的依賴關系, 并且按照順序加載這些依賴,可以了解為按照順序多次執行insmod。
depmod:建立子產品依賴檔案。modprobe是怎麼知道一個給定子產品所依賴的其他的子產品呢?在這個過程中,depmod起到了決定性作用,當執行modprobe時, 它會在子產品的安裝目錄下搜尋module.dep檔案,這是depmod建立的子產品依賴關系的檔案。
rmmod:删除子產品:
insmod+子產品名稱
lsmod:檢視所有子產品。
modinfo:顯示子產品中的幾個宏的定義。如協定、作者等等。
讓系統自動加載子產品需要用到指令depmod和modprobe。
首先需要将我們想要自動加載的子產品統一放到 /lib/modules/核心版本 目錄下,核心版本使用
uname -r
查詢;
其次使用depmod建立子產品之間的依賴關系,指令
depmod -a
;
這個時候我們就可以在modules.dep中看到子產品依賴關系,可以使用如下指令檢視:
cat /lib/modules/核心版本/modules.dep | grep calculation
最後在/etc/modules加上我們自己的子產品。
-
注意在該配置檔案中,子產品不寫成.ko形式代表該子產品與核心緊耦合,有些是系統必須要跟核心緊耦合,比如mm子系統, 一般寫成.ko形式比較好,如果出現錯誤不會導緻核心出現panic錯誤,如果內建到核心,出錯了就會出現panic。
然後重新開機開發闆,使用指令lsmod即可檢視我們的子產品開機就被加載到核心了。
實際上,符号指的就是核心子產品中使用 EXPORT_SYMBOL 聲明的函數和變量。當子產品被裝入核心後,它所導出的符号都會記錄在公共核心符号表中。可供給其它子產品使用。
導出方法:
- 符号必須在子產品檔案的全局部分導出,不能在函數中使用。
- _GPL使得導出的子產品隻能被GPL許可的子產品使用。
- 編譯我們的子產品時,這兩個宏會被拓展為一個特殊變量的聲明,存放在ELF檔案中。 具體也就是存放在ELF檔案的符号表中:
- st_name: 是符号名稱在符号名稱字元串表中的索引值;
- st_value: 是符号所在的記憶體位址;
- st_size: 是符号大小;
- st_info: 是符号類型和綁定資訊;
- st_shndx: 表示符号所在section。
EXPORT_SYMBOL(name)
EXPORT_SYMBOL_GPL(name) // name為要導出的标志
調用方法(例子):
extern int name;
Linux核心提供一個宏來實作子產品的參數傳遞:
#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 | 其它使用者具有寫權限 |
子產品參數使用示例
子產品源碼:
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/
- 本文連結:https://www.cnblogs.com/lizhuming/p/14551899.html
- 野火