- 一、简介
- 二、一个简单的内核模块代码
- 三、模块内常用符号说明
- 四、内核模块加载
- 1、模块加载函数
- 2、模块加载
- 3、查看设备上当前模块的信息
- 4、查看模块依赖
- 五、内核模块卸载
- 1、模块卸载函数
- 2、模块卸载
- 六、模块参数
- 七、导出符号
- 八、编译
linux内核架构庞大功能众多,包含非常多的组件。并不是所有功能都是用户需要的,也不可能稍微修改一些功能就重新全编linux内核。
-
当前linux使用模块(module)的机制解决这个问题
- 1、module可以单独编译
- 2、module可以在内核启动后动态加载或卸载
#include三、模块内常用符号说明#include #include static int __init module_init_test(void) { pr_info("module init test!"); pr_info("module init end!"); return 0; } static void __exit module_exit_test(void) { pr_info("module exit test!"); pr_info("module exit end!"); return; } module_init(module_init_test); module_exit(module_exit_test); MODULE_AUTHOR("zhuang da shuai ge"); MODULE_DESCRIPTION("just a test module"); MODULE_LICENSE("GPL");
module_init();
module_exit();
module_param();
EXPORT_SYMBOL();
EXPORT_SYMBOL_GPL();
模块声明相关:
MODULE_AUTHOR("***");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("***");
MODULE_ALIAS("***");
MODULE_VERSION("***");
等
四、内核模块加载
1、模块加载函数
代码中static int __init module_init_test(void)就是一个模块加载函数,一般以__init标识,使用module_init(module_init_test)指定。
模块加载时,实际就是运行此函数。返回整形值,正常返回0,其它异常返回值在
模块加载有insmod和modprobe两种方式:
insmode ./test.ko modprobe test
例如:
~# insmod test.ko ~# dmesg -c [148348.202699] module init test! [148348.202699] module init end!
两种模块加载的方法实际都是运行模块加载函数。modprobe功能更加强大,会自动加载模块的依赖。
3、查看设备上当前模块的信息在linux环境下,使用lsmod可以查看设备上当前已经加载的模块,该命令实际上是解析/proc/modules.
~# lsmod |grep test test 16384 0 ~# cat /proc/modules |grep test test 16384 0 - Live 0xffffffffc0336000 (OE)
另外,已加载的模块的信息,也存在/sys/module目录下。
使用modeinfo <模块名> 可以查看模块信息。
~# modinfo test filename: /lib/modules/4.19.0-12-2-amd64/extra/test.ko license: GPL description: just a test module author: zhuang da shuai ge depends: retpoline: Y name: test vermagic: 4.19.0-12-2-amd64 SMP mod_unload modversions4、查看模块依赖
参考以前写的文章:查看内核模块依赖关系和动态库依赖关系
五、内核模块卸载 1、模块卸载函数代码中static void __exit module_exit_test(void)就是一个模块卸载函数,一般以__exit 标识,使用module_exit(module_exit_test)指定。
模块卸载时,实际就是调用此函数。
rmmod test modprobe -f test (卸载模块和其依赖)
模块卸载可直接用rmmod,也可以用modprobe r 模块名 方式,使用modprobe r 会同时卸载相关依赖。
~# rmmod test ~# dmesg -c [ 4175.680292] module exit test! [ 4175.680292] module exit end!六、模块参数
使用module_param(参数名,参数类型,参数读写权限) 定义模块的参数。例如:
static int test_param = 10; module_param(test_param, int, S_IGUGO);
如此定义后,加载内核模块时,用户可直接传递模块参数的值:
modprobe(insmod) 模块名 参数名=参数值 modprobe(insmod) test test_param=11
如此加载模块,test_param值则被定义为11。若加载模块时不传递参数值,则test_param为默认值10。
七、导出符号/proc/kallsyms文件中记录了内核符号表,记录符号以及符号所在的内存地址。在这个符号表中的接口,可被其它模块调用。
模块中可用如下宏将符号导出到内核符号表中,导出的符号可被其它模块使用:
EXPORT_SYMBOL(); EXPORT_SYMBOL_GPL();八、编译
obj-m := modulename.o
模块包含多个文件时:
obj-m := modulename.o modulename-objs := test1.o test2.o



