1.模块化编程原因:Linux 内核庞大,需要大量组件,一起集成会导致镜像文件过大
2.内核模块操作命令
a) 加载:insmod xxx.ko
b) 卸载:rmmod xxx.ko
c) 查看:lsmod | grep xxx.ko
3.内核模块编程头文件必备
a) #include<linux/init.h>
b) #include<linux/modules.h>
4.内核模块函数入口
a) module_init(function_name)
b) module_exit(function_name)
c) 解释:
i. 当终端调用insmod 命令时,module_init(function_name)函数将被内核调用
ii. rmmod 命令调用 module_exit(function_name)
5.编程模型:
#include<linux/init.h>
#include<linux/modules.h>
static int hell_init(void)
{
printk(KERNEL_WARNING,”HELLO WORLD!\N”);
.....;
return 0;
}
static void hell_exit(void)
{
....;
}
module_init(hell_init);
module_exit(hell_exit);
6.Makefile 编写格式
a) obj-m := xxx.o /*obj-m指定编译成模块文件,xxx.o为目标文件*/
b) xxx-objs := file1.o file2.o /*针对多文件内核模块*/
c) 定义保存内核源码的路径
i. KERNELPATH:= /......
d) 目标
all:
make -C $(KERNELPATH) M=$(PWD) modules CROSS_COMPILE=arm-llinux- ARCH=arm
解析:-C 指定源码依赖所在路径
M 指定模块文件所在路径
7.模块附加信息申明
a) MODULE_LICENSE(“GPL等”)
b) MODULE_AUTHOR(“作者”)
c) MODULE_DESCRIPTION(“模块信息描述”)
d) MODULE_VERSION(“版本申明”)
e) ....
8.模块参数传递
a) 应用程序:
i. main(int args,const char* argv)
1. args:输入参数个数
2. argv:保存输入的参数
b) 内核传参:
i. moduel_param(name,type,perm)
1. name:变量名
2. type:类型:
a) bool;
b) int;
c) charp:字符串
3. perm:访问权限
a) S_IRUGO:读权限
b) S_IWUSR:写权限
4. 使用时加载后添加变量参数:
a) 例如
i. int a=1;
ii. char* sr;
iii. moduel_param(a,int ,S_IRUGO)
iv. moduel_param(sr,charp,S_IWUSR)
v. 加载时 insmod a=3;
9.内核符号及导出
a) 如果模块需要将定义的函数交给其他外部模块使用,则必须使用模块符号导出宏
b) 模块导出
i. EXPORT_SYMBOL(符号名)
ii. EXPORT_SYMBOL(符号名) ===只能用于包含GPL许可证
iii. 外部调用该符号时需要使用
1. extern 关键字申明