初始化硬件設備。ide
這是驅動程序最基本的功能,初始化經過總線識別設備,訪問設備寄存器,按照需求配置設備地端口,設置中斷等。函數
向操做系統提供統一的軟件接口。
設備驅動程序向操做系統提供了一類設備通用的軟件接口,如硬盤設備向操做系統提供了讀寫磁盤塊、尋址等接口,不管是哪一種品牌的硬盤驅動向操做系統提供的接口都是一致的。
提供輔助功能。
現代計算機的處理能力愈來愈強,操做系統有一類虛擬設備驅動,能夠模擬真實設備的操做,如虛擬打印機驅動向操做系統提供了打印機的接口,在系統沒有打印機制狀況下仍然能夠執行打印操做。
運行環境不一樣。
內核模塊運行在內核空間,能夠訪問系統的幾乎全部的軟硬件資源;普通應用程序運行在用戶空間,能夠訪問的資源受到限制。這也是內核模塊與普通應用程序最主要的區別。因爲內核模塊能夠得到與操做系統內核相同的權限,所以在編程的時候應該格外注意,可能在用戶空間看到的一點小錯誤在內核空間就會致使系統崩潰。
功能定位不一樣。
普通應用程序爲了完成某個特定的目標,功能定位明確;內核模塊是爲其餘的內核模塊以及應用程序服務的,一般提供的是通用的功能。
函數調用方式不一樣。
內核模塊只能調用內核提供的函數,訪問其餘的函數會致使運行異常;普通應用程序可能調用自身之外的函數,只要能正確鏈接就有運行。
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);
|