(一) LINUX“内核模块”的开发:
1. 如何使用需要的组件
a) 把所有的组件都编译进内核文件:
i. 缺陷1:内核文件过大
ii. 缺陷2:如果要添加或删除某个组件,需要重新编译整个内核
b) 使用“内核模块”的机制:
i. 模块本身并不被编译进内核文件
ii. 以根据需求,在内核运行期间动态的安装或卸载。
2. 程序结构:例:vi hello.c
a) #include <linux/init.h>
b) #include <linux/module.h> 头文件
c) static int hello_init(void)
d) {
e) printk(KERN_WARNING "Hello, world !\n"); 打印函数
f) return 0;
g) }
h) static void hello_exit(void)
i) {
j) printk(KERN_INFO "Goodbye, world\n");
k) }
l) module_init(hello_init); 模块加载函数(必需)
m) module_exit(hello_exit); 模块卸载函数(必需)
3. 模块的编译:使用Makefile,基本格式都差不多,这里不能使用GCC
a) 编写单文件的Makefile:注意M大写
Ifneq ($(KERNELRELEASE),) 第1次变量为空,执行else;
obj-m := hello.o 目标名,需要根据情况修改
else
kDIR := /lib/modules/2.6.18-53.el5/build 内核源代码路径:根据情况修改
all:
make –C $(KDIR) M=$(PWD)modules –C进入目录,使用目录中的makefile来编译当前目录下的模块代码,再次进入该代码,执行if真
clean:
rm –f *.ko *.o *.mod.o *.mod.c *.symvers
endif
i. 报错:missing separator 缺少分隔符:注意分隔符,格式是否正确
ii. 报错:没有找到Makefile文件,查看M是否大写,文件名写对没
b) 编写多文件的Makefile:需要改一个地方
i. obj-m := hello.o
ii. hello-objs := main.o add.o
4. 安装与卸载
a) 加载insmod :insmod hello.ko
b) 卸载rmmod :rmmod hello
c) 查看lsmod
d) 加载modprobe (modprobe hello): modprobe 如同insmod, 也是加载一个模块到内核。它的不同之处在于它会根据文件/lib/modules/<$version> /modules.dep来查看要加载的模块, 看它是否还依赖于其他模块,如果是,modprobe 会首先找到这些模块, 把它们先加载到内核。
5. 注意:应用程序是从头(main)到尾执行任务,执行结束后从内存中消失。内核模块则是先在内核中注册自己以便服务于将来的某个请求,然后它的初始化函数结束,此时模块仍然存在于内核中,直到卸载函数被调用,模块才从内核中消失。
6. 模块可选信息:
a) 许可证申明:宏MODULE_LICENSE用来告知内核, 该模块带有一个许可证,常用”GPL” :MODULE_LICENSE(”GPL”);
b) 作者申明(可选):MODULE_AUTHOR(“Simon Li");
c) 模块描述(可选):MODULE_DESCRIPTION("Hello World Module");
d) 模块版本(可选):MODULE_VERSION("V1.0");
e) 模块别名(可选):MODULE_ALIAS("a simple module");
f) 模块参数:模块参数用于在加载模块时传递参数给模块。
i. module_param(name,type,perm):module_param(a,int, S_IRUGO);
ii. name是模块参数的名称,
iii. type是这个参数的类型:bool:布尔型int:整型charp:字符串型
iv. perm是模块参数的访问权限。
1) S_IRUGO:任何用户都对/sys/module中出现的该参数具有读权限
2) S_IWUSR:允许root用户修改/sys/module中出现的该参数
&nbs