KO之间互相调用

需求

假设有两个KO,命名为moduleA.KO,moduleB.KO,现在要实现在moduleB.KO中调用moduleA.KO中的函数。

实现

ModuleA实现

源码:

#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h>  void moduleA_func(void) {     printk("moduleA functionrn"); }  static int __init moduleA_init(void) {     printk("moduleA init!rn");      return 0; }  static void __exit moduleA_exit(void) {     printk("moduleA exit!rn"); }  EXPORT_SYMBOL_GPL(moduleA_func);  MODULE_AUTHOR("moduleA"); MODULE_DESCRIPTION("moduleA functions"); MODULE_LICENSE("GPL v2");  module_init(moduleA_init); module_exit(moduleA_exit); 

moduleA导出符号moduleA_func。

编译Makefile实现:

# Kernel modules obj-m += moduleA.o  KVERS = $(shell uname -r)  # Specify flags for the module compilation. #EXTRA_CFLAGS=-g -O0  OUTPUT_DIR := $(shell pwd)  build: kernel_modules  kernel_modules: 	make -C /lib/modules/$(KVERS)/build M=$(OUTPUT_DIR) modules  clean: 	make -C /lib/modules/$(KVERS)/build M=$(OUTPUT_DIR) clean 

编译:

$ make $ more Module.symvers 0xcaecb33a      moduleA_func    /home/grace/ko_test/moduleA/moduleA     EXPORT_SYMBOL_GPL 

可以看出,moduleA_func已经在导出的符号表中了。

ModuleB实现

源码:

#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h>  extern void moduleA_func(void);  static int __init moduleB_init(void) {     printk("moduleB init!rn");      moduleA_func();      return 0; }  static void __exit moduleB_exit(void) {     printk("moduleB exit!rn"); }  MODULE_AUTHOR("moduleB"); MODULE_DESCRIPTION("moduleB functions"); MODULE_LICENSE("GPL v2");  module_init(moduleB_init); module_exit(moduleB_exit); 

编译Makefile:

# Kernel modules obj-m += moduleB.o  KVERS = $(shell uname -r)  # Specify flags for the module compilation. #EXTRA_CFLAGS=-g -O0  # 引用moduleA.ko的符号表, 需要先编译SDK才能得到, 路径为绝对路径 KBUILD_EXTRA_SYMBOLS += /home/grace/ko_test/moduleA/Module.symvers  OUTPUT_DIR := $(shell pwd)  build: kernel_modules  kernel_modules: 	make -C /lib/modules/$(KVERS)/build M=$(OUTPUT_DIR) modules  clean: 	make -C /lib/modules/$(KVERS)/build M=$(OUTPUT_DIR) clean 

测试

1、插入moduleA.ko

$ sudo insmod moduleA.ko $ sudo dmesg -c [ 1567.642413] moduleA: loading out-of-tree module taints kernel. [ 1567.642507] moduleA: module verification failed: signature and/or required key missing - tainting kernel [ 1567.642823] moduleA init! $ cat /proc/kallsyms | grep moduleA_func ffffffffc071b030 r __ksymtab_moduleA_func       [moduleA] ffffffffc071b07b r __kstrtab_moduleA_func       [moduleA] ffffffffc071b040 r __kcrctab_moduleA_func       [moduleA] ffffffffc071a000 t moduleA_func [moduleA] 

2、插入moduleB.ko

$ sudo dmesg -c [ 1900.514577] moduleB init! [ 1900.514580] moduleA function 

可以看出,moduleB成功调用到了moduleA的moduleA_func函数。

常见错误

1、moduleA没有编译就编译了ModuleB

这时候会提示:WARNING: "moduleA_func" [/home/grace/ko_test/moduleB/moduleB.ko] undefined!

2、没有在ModuleB的Makefile中添加KBUILD_EXTRA_SYMBOLS

这时候会提示:WARNING: "moduleA_func" [/home/grace/ko_test/moduleB/moduleB.ko] undefined!

3、注意:KBUILD_EXTRA_SYMBOLS后面跟的是绝对路径

总结

ModuleB.ko调用ModuleA.ko的使用步骤:

  1. 先编译ModuleA.ko, 得到KO的符号表, 也就是Module.symvers文件
  2. 再编译ModuleB.ko, 需要在Makefile中指定ModuleA.ko的符号表位置KBUILD_EXTRA_SYMBOLS+="符号表位置",并且使用绝对路径方式。
  3. 插入时,需要先插入ModuleA.ko,再插入ModuleB.ko
  4. 卸载时,需要先卸载ModuleB.ko,再卸载ModuleA.ko,否则会提示:rmmod: ERROR: Module moduleA is in use by: moduleB
发表评论

评论已关闭。

相关文章

当前内容话题