《Linux4.0設備驅動開發詳解》筆記--第四章:Linux內核模塊

4.1 內核模塊程序結構

  • 加載:insmod,modprobe(同時加載模塊的依賴模塊)
  • 卸載:rmmod
  • 查看已加載的模塊及模塊間的依賴關係:lsmod,其實是分析/proc/modules文件
  • 已加載的模塊信息放在/sys/module目錄下,沒加載一個模塊就會在該目錄下生成一個以模塊名命名的目錄,「tree -a」可獲取目錄樹
  • 模塊許可聲明:申明許可權限,不然將收到內核被污染警告,通常申明爲MODULE_LICENSE(「GPL v2」)語句申明採用GPL v2.
  • 模塊參數(可選):模塊被加載的時候能夠傳遞給它的值,它自己對對應模塊的內部的全局變量
  • 模塊導出符(可選):其餘模塊可使用模塊導出的函數和變量
  • 模塊做者等信息聲明

4.2 模塊加載函數

  • Linux內核模塊加載函數通常以__init標識申明,如
static int __init initialization_function(void)
{
    /*初始化代碼*/
}
module_init(initialization_function);

初始化成功返回0,不然返回錯誤碼。linux

  • request_module(const char* fmt, …):靈活加載內核模塊
  • 數據也能夠定義爲__initdata,只是在初始化的階段須要的數據,結束後釋放佔用的內存

4.4 模塊卸載函數

通常以__exit標識申明,如數組

static void __exit cleanup_function(void)
{
    /*釋放代碼*/
}
module_exit(cleanup_function);

被直接編譯進內核的模塊的卸載函數會被省略,不編譯進內核,由於模塊被內置了,也就不會被卸載。markdown

4.5 模塊參數

  • module_param(參數名,參數類型,參數讀寫權限):爲模塊定義一個參數,以下定義一個int參數和char指針參數
static char *book_name = "dissecting Linux Deice Driver";
module_param(book_name, char, S_IRUGO);

static int book_num = 4000;
module_param(book_num, int, S_IRUGO);

「insmod (或modprobe) 模塊名 參數名 = 參數值」,不傳遞則用缺省值,模塊被內置時用bootloader經過bootargs裏設置「模塊名.參數 = 值」給內置模塊傳遞參數。函數

  • 參數數組:module_param_array(數組名,數組類別,數組長度,參數讀寫權限)
  • /sys/module下有已加載模塊命名的目錄,當「參數讀寫權限」爲0,則此參數不存在sysfs文件系統下對應的節點,不然此模塊的目錄下會出現parameter目錄,其中包含以參數名命令的文件節點,文件權限與設定的權限一致。
  • 容許insmod和modprobe命令時,用逗號隔開輸入的數組元素
  • 例:定義兩個參數的模塊
/*====================================================================== A kernel module: book This example is to introduce module params The initial developer of the original code is Baohua Song <author@linuxdriver.cn>. All Rights Reserved. ======================================================================*/
#include <linux/init.h> 
#include <linux/module.h> 
MODULE_LICENSE("Dual BSD/GPL");                                

static char *book_name = "dissecting Linux Device Driver";              
static int num = 4000;                                

static int book_init(void)                                
{                                
    printk(KERN_INFO " book name:%s\n",book_name);                        
    printk(KERN_INFO " book num:%d\n",num);                               
    return 0;                                
}                                
static void book_exit(void)                                
{                                
    printk(KERN_INFO " Book module exit\n ");                            
}                                
module_init(book_init);                                
module_exit(book_exit);                                
module_param(num, int, S_IRUGO);                                
module_param(book_name, charp, S_IRUGO);

MODULE_AUTHOR("Song Baohua, author@linuxdriver.cn");
MODULE_DESCRIPTION("A simple Module for testing module params");
MODULE_VERSION("V1.0");

經過insmod加參數和不加參數實驗,在/var/log/messages文件中查看內核的輸出
在/sys/module/book/parameters目錄下輸入tree查看參數文件節點spa

4.6 導出符號

  • /proc/kallsyms文件記錄了符號及符號所在的內存地址
  • 導出符號:EXPORT_SYSBOL(符號名),EXPORT_SYSBOL_GPL(符號名)(只適用於包含GPL許可權的模塊)
  • 例:
/*====================================================================== A simple kernel module to introduce export symbol The initial developer of the original code is Baohua Song <author@linuxdriver.cn>. All Rights Reserved. ======================================================================*/
#include <linux/init.h> 
#include <linux/module.h> 
MODULE_LICENSE("Dual BSD/GPL");                                

int add_integar(int a,int b)                                
{                                
    return a+b;                             
} 

int sub_integar(int a,int b)                                
{                                
    return a-b;                             
}                            

EXPORT_SYMBOL(add_integar);
EXPORT_SYMBOL(sub_integar);

4.7 模塊申明與描述

  • MODULE_AUTHOR(author);
  • MODULE_DESCRIPTION(description);
  • MODULE_VERSION(version_string);
  • MODULE_DEVICE_TABLE(table_info);
  • MODULE_ALIAS(alternate_name);
  • 對於USB, PCI等設備驅動,一般建立一個MODULE_DEVICE_TABLE來代表驅動模塊支持的設備

4.8 模塊的使用計數

  • try_module_get(&module)和module_put(&module):模塊計數管理接口
  • try_module_get(&module):增長模塊使用計數,返回0,調用失敗,但願使用的的模塊不存在或正在被卸載
  • module_put(&module):減小模塊使用計數
  • 模塊的使用計數通常不禁模塊自己管理,由內核更底層的代碼(總線驅動或者此類設備共用的核心模塊)來實現,以簡化驅動開發
  • 當設備正在使用的時候,模塊不能夠被卸載

4.9 模塊編譯

  • Makefile
  • 模塊包含多個.c文件,則Makefile寫法
obj-m := modulename.o
modulename-objs := file1.o file2.o ...
相關文章
相關標籤/搜索