初始化硬件設備。
這是驅動程序最基本的功能,初始化通過總線識別設備,訪問設備寄存器,按照需求配置設備地端口,設置中斷等。
向操作系統提供統一的軟件接口。
設備驅動程序向操作系統提供了一類設備通用的軟件接口,如硬盤設備向操作系統提供了讀寫磁盤塊、尋址等接口,無論是哪種品牌的硬盤驅動向操作系統提供的接口都是一致的。
提供輔助功能。
現代計算機的處理能力越來越強,操作系統有一類虛擬設備驅動,可以模擬真實設備的操作,如虛擬打印機驅動向操作系統提供了打印機的接口,在系統沒有打印機制情況下仍然可以執行打印操作。
運行環境不同。
內核模塊運行在內核空間,可以訪問系統的幾乎所有的軟硬件資源;普通應用程序運行在用戶空間,可以訪問的資源受到限制。這也是內核模塊與普通應用程序最主要的區別。由於內核模塊可以獲得與操作系統內核相同的權限,因此在編程的時候應該格外注意,可能在用戶空間看到的一點小錯誤在內核空間就會導致系統崩潰。
功能定位不同。
普通應用程序爲了完成某個特定的目標,功能定位明確;內核模塊是爲其他的內核模塊以及應用程序服務的,通常提供的是通用的功能。
函數調用方式不同。
內核模塊只能調用內核提供的函數,訪問其他的函數會導致運行異常;普通應用程序可能調用自身以外的函數,只要能正確連接就有運行。
1 2 | static int __init init_func( void ); //初始化函數 static void __exit exit_func( void ); //清除函數 |
static修飾符的作用是函數僅在當前文件有效,外部不可見;
__init關鍵字告訴編譯器,該函數代碼在初始化完畢後被忽略;
__exit關鍵字告訴編譯器,該代碼僅在卸載模塊的時候被調用;
insmod命令加載內核模塊的時候不檢查內核模塊的符號是否已經在內核中定義。
modprobe不僅檢查內核模塊符號表,而且還會檢查模塊的依賴關係。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* 內核模塊: ModuleHelloWorld.c */ #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> MODULE_LICENSE( "GPL" ); MODULE_AUTHOR( "Mystety" );
/* init function */ static int __init hello_init( void ) {
printk(KERN_ALERT "(init)Hello,World!\n" );
return 0; } /* exit function */ static void __exit hello_exit( void ) {
printk(KERN_ALERT "(exit)Bye-bye,Mystery!\n" ); } module_init(hello_init); module_exit(hello_exit); |
1 | sudo apt-get install linux- source |
1 2 3 4 5 6 7 8 | ifneq ($(KERNELRELEASE),)
obj-m := ModuleHelloWorld.o else
KERNELDIR := /lib/modules/ $(shell uname -r) /build
PWD := $(shell pwd ) default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif |
1 | lsmod | grep ModuleHelloWorld |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> MODULE_LICENSE( "GPL" ); MODULE_AUTHOR( "Mystety" ); static int initValue = 0; //模塊參數 initValue = <int value> static char *initName = NULL; //模塊參數 initName = <char*> module_param(initValue, int , S_IRUGO); module_param(initName, charp, S_IRUGO); /* init function */ static int __init hello_init( void ) {
printk(KERN_ALERT "initValue = %d initName = %s \n" ,initValue,initName); //打印參數值
printk(KERN_ALERT "(init)Hello,World!\n" );
return 0; } /* exit function */ static void __exit hello_exit( void ) {
printk(KERN_ALERT "(exit)Bye-bye,Mystery!\n" ); }
module_init(hello_init); module_exit(hello_exit); |