使用kallsyms_lookup_name函数,可以在内核态实现类似动态链接的功能,是的模块之间的依赖进一步解耦合。
在hello2模块中,有一个函数KKK_test_func,进行符号导出。在模块hello中调用了KKK_test_func函数。如果单纯使用符号文件的形式,hello模块在insmod的时候会要求hello2模块加载,否则会报告unknown symbols。
某些场景下,可能按需对于hello2模块进行加载。当没有条件时不加载hello2模块,此时hello模块也可以加载,调用KKK_test_func时可对KKK_test_func符号调用kallsyms_lookup_name函数进行查表,查到了可以调用,查不到(NULL)就不调用(整个调用过程可由程序控制)。
当hello2模块没有加载时,通过执行cat /proc/kallsyms | grep KKK_test_func,会找不到对应符号。当hello2模块加载后,cat此文件可以找到相应符号。
使用kallsyms_lookup_name函数需要#include <linux/kallsyms.h>
//hello2.c
#include <linux/init.h>
#include <linux/module.h>
static int __init hello2_init(void)
{
printk(KERN_INFO "%s: init called\n", __func__);
return 0;
}
static void __exit hello2_exit(void)
{
printk(KERN_INFO "%s: exit called\n",__func__);
}
int KKK_test_func(int flag)
{
printk(KERN_INFO "FUNC: %s called, flag=%d\n",__func__, flag);
return 0;
}
EXPORT_SYMBOL_GPL(KKK_test_func);
module_init(hello2_init);
module_exit(hello2_exit);
MODULE_AUTHOR("duanjsh <duanjsh@qq.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A simple test module!");
#hello2_Makefile
PWD = $(shell pwd)
KVERS =$(shell uname -r)
KERNDIR =/lib/modules/${KVERS}/build/
obj-m += hello2.o
build: kernel_modules
kernel_modules:
make -C $(KERNDIR) M=$(PWD) modules
clean:
make -C $(KERNDIR) M=$(PWD) clean
//hello.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
int (*fptr)(int) = NULL;
static int __init hello_init(void)
{
printk(KERN_INFO "%s: init called\n", __func__);
fptr = kallsyms_lookup_name("KKK_test_func");
if (!fptr) {
printk("Didn't found KKK_test_func\n");
return 1;
}
printk("found KKK_test_func = %p\n", fptr);
fptr(0);
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "%s: exit called\n",__func__);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("duanjsh <duanjsh@qq.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A simple test module!");
#hello_Makefile
PWD = $(shell pwd)
KVERS =$(shell uname -r)
KERNDIR =/lib/modules/${KVERS}/build/
obj-m += hello.o
build: kernel_modules
kernel_modules:
make -C $(KERNDIR) M=$(PWD) modules
clean:
make -C $(KERNDIR) M=$(PWD) clean
以上在debian10 4.19.0内核测试通过。
Linux deb10 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) x86_64 GNU/Linux