天天看點

Linux核心子產品子產品(Module)Linux核心子產品程式結構

目錄

子產品(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
           

繼續閱讀