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,否則返回錯誤碼。
- request_module(const char* fmt, …):靈活載入核心模組
- 資料也可以定義為__initdata,只是在初始化的階段需要的資料,結束後釋放佔用的記憶體
4.4 模組卸載函數
一般以__exit標識申明,如
static void __exit cleanup_function(void)
{
/*釋放程式碼*/
}
module_exit(cleanup_function);
被直接編譯進核心的模組的卸載函數會被省略,不編譯進核心,因為模組被內置了,也就不會被卸載。
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查看參數檔節點
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 ...
留言列表