1.简介
Linux 可加载内核模块(Loadable Kernel Modules,简称 LKMs 或 LKM)是 Linux 内核的一个重要特性,它允许用户动态地添加或删除内核功能而不需要重新启动整个系统。这种灵活性使得内核可以根据需要加载不同的功能模块,从而节省内存资源并提高系统的安全性。
1.1.基本概念
- 模块:是一个独立的程序,它可以被动态地加载到内核中以扩展其功能。模块可以包含设备驱动程序、文件系统实现、网络协议栈组件等。
- 模块生命周期:
- 加载:模块通过insmod或modprobe命令加载到内核中。
- 运行:模块加载后会成为内核的一部分,可以访问内核的数据结构和资源。
- 卸载:通过rmmod命令卸载模块,使其从内核中移除。
2.实战
2.1.编写模块
hellomodule.c
#include <linux/module.h>
#include <linux/init.h>
/**
* @brief This function is called, when the module is loaded into the kernel
*/
static int __init hello_init(void) {
printk("Hello, Kernel!\n");
return 0;
}
/**
* @brief This function is called, when the module is removed from the kernel
*/
static void __exit hello_exit(void) {
printk("Goodbye, Kernel\n");
}
module_init(hello_init);
module_exit(hello_exit);
/* Meta Information */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZOOM");
MODULE_DESCRIPTION("Hello World Module");
MODULE_VERSION("1.0");
2.2.编译模块
模块通常是用C语言编写,并且需要与内核版本相匹配的内核源码进行编译。编译过程通常涉及以下几个步骤:
- 准备开发环境:确保安装了内核开发包和编译工具链(如GCC)。
- 编写 Makefile:定义如何编译和链接模块。
- 编译模块:使用make命令编译模块。
Makefile
obj-m += hellomodule.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
2.3.加载和卸载模块
加载和卸载模块
一旦模块被编译并准备好,就可以使用以下命令来加载或卸载模块:
加载模块:
insmod hello.ko
卸载模块:
rmmod hello
如果模块依赖于其他模块,可以使用modprobe命令自动处理依赖关系:
modprobe hello
2.4.调试和故障排查
- 查看模块信息:使用lsmod命令可以查看已加载的模块列表。
- 查看模块参数:使用cat /sys/module/<module_name>/parameters可以查看模块的参数值。
- 调试信息:内核的日志可以通过dmesg命令查看,这有助于调试模块中的问题。
2.5.其他注意事项
- 模块参数:模块可以在加载时传递参数,通过module_param宏定义参数,并在模块中使用module_param宏来声明它们。
- 内核版本兼容性:确保模块与当前内核版本兼容,因为内核API可能会随着不同版本发生变化。