LKM(Linux kernel module)作为Linux内核的插件,其安装和卸载都很方便(热插拔),可以满足一些需要特殊内核操作而不想重新编译整个内核的场景,在存储和安全厂商的产品中,LKM使用非常广泛。
Demo1
下面以一个非常简单的内核模块来了解LKM的使用
编写.c文件
/* hello-5.c */
#include <linux/module.h> //Needed by all modules
#include <linux/kernel.h> //Needed for KERN_INFO
#include <linux/moduleparam.h> //参数处理相关头文件
#include <linux/init.h>
#include <linux/stat.h>
MODULE_LICENSE("GPL"); //声明Licesne
MODULE_AUTHOR("Hunk He"); //声明模块作者
static int param_cnt = 0;
static char *param_arr[3] = {"", "", ""};
module_param_array(param_arr, charp, ¶m_cnt, 0644); //接收模块参数,参数名为param_arr,类型是字符串数组
//MODULE_PARAM_DESC(param_arr, "My param array[up to 3]."); //参数描述信息,这里有奇怪编译错误
static int __init hello_5_init(void)
{
printk(KERN_INFO "Hello world 5.\n"); //printk是内核的打印函数,可以向系统日志打印log
int i;
for( i = 0; i < 3; ++i) {
printk(KERN_INFO "param_arr[%d] = %s.\n", i, param_arr[i]);
}
return 0;
}
static void __exit hello_5_exit(void)
{
printk(KERN_INFO "Goodbye world 5.\n");
}
//实际上,模块安装卸载函数的用法还有好几种,可以参考References中的guide
module_init(hello_5_init); //模块加载函数,用modprobe或者insmod命令安装模块时被调用
module_exit(hello_5_exit); //模块卸载函数,用rmmod命令卸载模块时被调用,可以执行一些清理还原操作
编译LKM
内核模块一定是绑定某个特定内核版本来进行编译的,所以需要用-C指定内核源路径,如果需要绑定编译和当前系统不同的内核版本,可以下载内核rpm包解压后来作为源路径编译。
#Makefile
obj-m += hello-5.o
all:
make -C /usr/src/kernels/3.10.0-862.11.6.el7.x86_64/ M=$(PWD) modules
clean:
make -C /usr/src/kernels/3.10.0-862.11.6.el7.x86_64/ M=$(PWD) clean
执行make命令编译后生成内核模块hello-5.ko,后缀.ko是LKM的特有格式。
$ ll | grep hello-5.ko
-rw-r--r-- 1 root root 104728 Apr 20 18:21 hello-5.ko
安装LKM
下面将用modprobe命令来演示安装hello-5,也可以用更老一些的insmod命令跟上模块路径来进行安装。
$ mkdir -p /lib/modules/$(uname -r)/hunk/demo #创建模块安装路径,一般是../组织名称/模块名称
$ cp hello-5.ko /lib/modules/$(uname -r)/hunk/demo #拷贝LKM
$/sbin/depmod #在依赖关系中自动添加模块相对路径,否则modprobe命令找不到模块
$ cat /lib/modules/$(uname -r)/modules.dep | grep hunk
hunk/demo/hello-5.ko:
$ /sbin/modprobe hello-5 param_arr=baidu,google,sina #安装模块,模块名不包含.ko后缀
$ lsmod | grep hello #检查模块是否正在运行
hello_5 12629 0 #注意此处的模块名称被转换了一下
root@n8-h27:/home/hunk/lkm/hello-5# modinfo hello_5 #modinfo可以查看模块详细信息,模块即使还没有安装到内核,也可以用此命令
filename: /lib/modules/3.10.0-862.11.6.el7.x86_64/hunk/demo/hello-5.ko
author: Hunk He
license: GPL
retpoline: Y
rhelversion: 7.5
srcversion: 6A562C1EA3F25D2CD3C1714
depends:
vermagic: 3.10.0-862.11.6.el7.x86_64 SMP mod_unload modversions
parm: param_arr:array of charp
$ cat /var/log/messages | grep param_arr
Apr 20 18:55:33 n8-h27 kernel: param_arr[0] = baidu.
Apr 20 18:55:33 n8-h27 kernel: param_arr[1] = google.
Apr 20 18:55:33 n8-h27 kernel: param_arr[2] = sina.
卸载LKM
$ rmmod hello_5
$ lsmod | grep hello
$ cat /var/log/messages | grep bye
Apr 20 18:59:34 n8-h27 kernel: Goodbye world 5.
References
https://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html #强烈推荐这篇文章