需求

假设有两个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 function\r\n");
} static int __init moduleA_init(void)
{
printk("moduleA init!\r\n"); return 0;
} static void __exit moduleA_exit(void)
{
printk("moduleA exit!\r\n");
} 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!\r\n"); moduleA_func(); return 0;
} static void __exit moduleB_exit(void)
{
printk("moduleB exit!\r\n");
} 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

KO之间互相调用的更多相关文章

  1. Java特性之多态父类与子类之间的调用

    问题描述: Java三大特性,封装.继承.多态,一直没搞懂其中多态是什么,最近研究了一下,关于父类和子类之间的调用.下面是一个测试类,源代码如下: package com.test; public c ...

  2. html iframe 元素之间的调用

    html iframe 元素之间的调用一.简介 一般需要引入一个独立页面的时候,我们会使用iframe.在业务需要的时候,我们需要在父页面与iframe页面之间进行交互.交互的时候,我们就需要使 用到 ...

  3. 两个APP之间怎么调用《IT蓝豹》

    两个app之间怎么调用?   (1):通过显示Intent 启动    首先:配置好B app 的action,即AndroidManifest.xml中声明 <intent-filter> ...

  4. 《同一个类中不同方法之间的调用相关问题(省略的类名或者this)》

    //同一个类中不同方法之间的调用相关问题(省略的类名或者this) class A { public void B() { System.out.println("b方法运行"); ...

  5. JAVA 构造方法之间的调用

    this:看上去,用来区分局部变量和成员变量的情况this:就是代表本类对象,this代表它所在方法所属对象的引用构造方法之间的调用只能通过this语句来完成构造方法之间进行调用时this语句只能出现 ...

  6. Iframe父页面与子页面之间的调用

    原文:Iframe父页面与子页面之间的调用 Iframe父页面与子页面之间的调用 专业词语解释如下:     Iframe:iframe元素是文档中的文档.     window对象: 浏览器会在其打 ...

  7. 使用DLL进行不同语言之间的调用(转)

    源:使用DLL进行不同语言之间的调用 __declspec(dllexport) 是告诉编译器用来导出函数的,在代码中不另作说明了. extern "C" 的意思就是用C的方式来导 ...

  8. synchronized修饰的方法之间相互调用

    1:synchronized修饰的方法之间相互调用,执行结果为There hello  ..因为两个方法(main,hello)的synchronized形成了互斥锁.  所以当main方法执行完之后 ...

  9. 对于应用之间的调用,如何选择rpc还是mq?

    两个系统之间的调用,是选择rpc呢还是mq,说一下你们系统的选择吧 比如rpc可以是简单的spring httpinvoker,但是前提是都是java应用而且都是用spring framework,可 ...

  10. Java基础21-构造函数之间的调用

    public class Test{ public static void main(String[] args){ Persion p2=new Persion("小明",22) ...

随机推荐

  1. Java-01enum常量特定方法

    OnJava8-Enum-常量特定方法 用枚举实现责任链模式 责任链(Chain Of Responsibility)设计模式先创建了一批用于解决目标问题的不同方法,然后将它们连成一条"链& ...

  2. Android笔记--案例:找回密码

    找回密码 具体实现: 登录成功: 报告密码不同: 报告验证码错误: 代码相关: 找回密码的界面很简单,不细说了,直接写就行 找回密码的逻辑实现: 下一次就去写数据存储啦! 拜拜!

  3. mybatis-plus 开发环境在控制台打印日志

    参考博客:https://blog.csdn.net/qq_32929057/article/details/109291919 # 注意在生产环境注释掉 mubatis-plus: configur ...

  4. 实践Pytorch中的模型剪枝方法

    摘要:所谓模型剪枝,其实是一种从神经网络中移除"不必要"权重或偏差的模型压缩技术. 本文分享自华为云社区<模型压缩-pytorch 中的模型剪枝方法实践>,作者:嵌入式 ...

  5. 控制论个人学习笔记-线性系统的校正方法&现代控制论基础

    note 2020-08-05搬运 下面的内容来自(我的CSDN博客)[https://blog.csdn.net/weixin_45183579/article/details/105201314] ...

  6. flutter issue---->Scaffold.of(context)

    当我们想showSnackBar的时候,需要通过Scaffold.of(context)得到Scaffold.但是如果这个context用错的话,flutter就会抛出错误.下面我们通过代码仔细看一下 ...

  7. Delete ␍eslint(prettierprettier)错误

    Delete ␍eslint(prettier/prettier)错误 今天在用HBuilder开发uniapp项目时,想换成vscode进行开发,但是用vscode打开之前的项目,eslint报错一 ...

  8. 计网学习笔记五 wireless && mobile networks

    老师把无线网络用一节课一遍过了-感觉没能学透,便课后自己总结,看书,找资料补充,把无线网络大概摸了个七七八八.虽然不算精细,但还能看!内容包括WLAN总概,WiFi-WLAN的实现,802.11规定的 ...

  9. 在 Linux 内公网、云服务器搭建一套 K8s 集群

    前言 本文讲述如果在 Linux 搭建内/公网 Kubernetes 集群的详细步骤,解决搭建过程中的问题. 准备工作 Linux CentOS 7.x 两台及以上,本文用的 7.6 本文配置默认是在 ...

  10. vue之数组与对象的检测与更新

    目录 说明 语法 示例 说明 MVVM会自动检测变量的变化,当变量改变,页面也会对应的变化,但是有一点需要注意,如果有一个对象增加值的时候,不能直接修改,需要使用Vue.set()方法 语法 Vue. ...