目錄
子產品(Module)
加載子產品
解除安裝子產品
檢視子產品資訊
Linux核心子產品程式結構
1、子產品加載函數
2、子產品解除安裝函數
3、子產品許可證聲明
4、子產品參數(可選)
5、子產品導出符号(可選)
6、子產品作者等資訊聲明(可選)
子產品使用計數
7、子產品的編譯
子產品(Module)
Linux核心的整體架構本就非常龐大, 其包含的元件也非常多。 而我們怎樣把需要的部分都包含在核心中呢?
一種方法是把所有需要的功能都編譯到Linux核心中。 這會導緻兩個問題:
1、生成的核心會很大
2、如果我們要在現有的核心中新增或删除功能, 将不得不重新編譯核心。
有沒有另一種機制可使得編譯出的核心本身并不需要包含所有功能, 而在這些功能需要被使用的時候, 其對應的代碼被動态地加載到核心中呢?
Linux提供了這樣的機制, 這種機制被稱為子產品(Module) 。 子產品具有這樣的特點:
1、子產品本身不被編譯入核心映像, 進而控制了核心的大小。
2、子產品一旦被加載, 它就和核心中的其他部分完全一樣。
加載子產品
簡單指令:iinsmod modName
子產品依賴指令:modprobe (加載子產品及其依賴的其他子產品)
解除安裝子產品
簡單指令:rmmod modName
子產品依賴指令:modprobe -r modName(解除安裝子產品及其依賴的其他子產品)
檢視子產品資訊
modinfo modName
資訊包括子產品作者、 子產品的說明、 子產品所支援的參數以及vermagic
Linux核心子產品程式結構
1、子產品加載函數
當通過insmod或modprobe指令加載核心子產品時, 子產品的加載函數會自動被核心執行, 完成本子產品的相關初始化工作。
static int _ _init initialization_function(void)
{
/* 初始化代碼 */
}
module_init(initialization_function);
2、子產品解除安裝函數
當通過rmmod指令解除安裝某子產品時, 子產品的解除安裝函數會自動被核心執行, 完成與子產品解除安裝函數相反的功能。
static void _ _exit cleanup_function(void)
{
/* 釋放代碼 */
}
module_exit(cleanup_function);
3、子產品許可證聲明
許可證(LICENSE) 聲明描述核心子產品的許可權限, 如果不聲明LICENSE, 子產品被加載時, 将收到核心被污染(Kernel Tainted) 的警告。
在Linux核心子產品領域, 可接受的LICENSE包括“GPL”、 “GPL v2”、 “GPL and additional rights”、 “Dual BSD/GPL”、 “Dual MPL/GPL”和“Proprietary”
4、子產品參數(可選)
子產品參數是子產品被加載的時候可以傳遞給它的值, 它本身對應子產品内部的全局變量。
static char *book_name = "dissecting Linux Device Driver";
module_param(book_name, charp, S_IRUGO);
static int book_num = 4000;
module_param(book_num, int, S_IRUGO);
調用指令:
insmod book.ko book_name='GoodBook' book_num=5000
5、子產品導出符号(可選)
核心子產品可以導出的符号(symbol, 對應于函數或變量) , 若導出, 其他子產品則可以使用本子產品中的變量或函數。
EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名);
#include <linux/init.h>
#include <linux/module.h>
int add_integar(int a, int b)
{
return a + b;
}
EXPORT_SYMBOL_GPL(add_integar);
int sub_integar(int a, int b)
{
return a - b;
}
EXPORT_SYMBOL_GPL(sub_integar);
MODULE_LICENSE("GPL v2");
導出的符号可以被其他子產品使用, 隻需使用前聲明一下即可
6、子產品作者等資訊聲明(可選)
MODULE_AUTHOR(author);
MODULE_DESCRIPTION(description);
MODULE_VERSION(version_string);
MODULE_DEVICE_TABLE(table_info);
MODULE_ALIAS(alternate_name);
子產品使用計數
用于增加子產品使用計數,若傳回為0,表示調用失敗,希望使用的子產品沒有被加載或正在被卸
載中。
int try_module_get(struct module *module);
用于減少子產品使用計數。
void module_put(struct module *module);
7、子產品的編譯
使用Makefile進行編譯
KVERS = $(shell uname -r)
# Kernel modules
obj-m += hello.o
# Specify flags for the module compilation.
#EXTRA_CFLAGS=-g -O0
build: kernel_modules
kernel_modules:
make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
clean:
make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean