【linux】驅動-2-內核模塊


前言

  • 以野火i.M 6U爲例

2. 內核模塊

本章節筆記主要理解內核模塊代碼框架和原理,分析一個簡單的內核模塊例子。
須要明確的是模塊驅動是兩回事。html

2.1 內核模塊概念

2.1.1 內核

內核,是一個操做系統的核心。是基於硬件的第一層軟件擴充,提供操做系統的最基本的功能, 是操做系統工做的基礎,決定着整個操做系統的性能和穩定性。
內核按照體系結構分爲:微內核宏內核linux

  • 參考圖:

2.1.2 內核模塊機制的引入

提升系統靈活性,在調試驅動的時候不須要從新編譯內核,也不須要從新啓動內核,只須要插入須要調試的驅動便可。
內核模塊的特色:框架

  • 模塊自己不被編譯入內核映像,這控制了內核的大小。
  • 模塊一旦被加載,它就和內核中的其它部分徹底同樣。

2.2 內核模塊

內核模塊編譯後會獲得一個 .koELF 文件。(ELF 文件能夠百度一下,也能夠參考野火的內核模塊章節。)
ELF 文件:這類文件包含了代碼和數據,能夠被用來連接成可執行文件或共享目標文件,靜態連接庫也能夠歸爲這一類。函數

2.2.1 內核模塊參考例程

必須內容可分爲如下幾點:性能

  • 入口函數:當經過insmod或modprobe命令加載內核模塊時,模塊的加載函數就會自動被內核執行,完成本模塊相關的初始化工做。
  • 出口函數:執行rmmod命令卸載模塊時,模塊卸載函數就會自動被內核自動執行,完成相關清理工做。
  • 協議:許可證聲明描述內核模塊的許可權限,若是模塊不聲明,模塊被加載時,將會有內核被污染的警告。

非必須內容:ui

  • 模塊參數:模塊參數是模塊被加載時,能夠傳值給模塊中的參數。
  • 模塊導出符號: 模塊能夠導出準備好的變量或函數做爲符號,以便其餘內核模塊調用。
  • 模塊的其餘相關信息: 能夠聲明模塊做者等信息。

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");

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中看到模塊依賴關係,可使用以下命令查看:日誌

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。
EXPORT_SYMBOL(name)
EXPORT_SYMBOL_GPL(name)  // name爲要導出的標誌

調用方法(例子):

extern int name;

2.2.5 模塊參數

模塊參數:模塊參數是模塊被加載時,能夠傳值給模塊中的參數。

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,則沒法查看該文件,也不會顯示在該路徑

參考

相關文章
相關標籤/搜索