初始化硬件设备。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);
|