一、问题整理

内核中两个模块,一个A,一个B,A模块中有操作函数,B模块要调用A模块的函数。

二、分析

这是一个驱动工程师经常遇到的一个问题,该问题其实是模块符号导出问题,实现该功能比较简单,借助EXPORT_SYMBOL()即可。

1. 什么是符号?

这里的符号主要指的是全局变量和函数,静态全局变量其实也可以被另外一个模块访问到。

2. 为什么要导出符号?



Linux内核采用的是以模块化形式管理内核代码。内核中的每个模块相互之间是相互独立的,也就是说A模块的全局变量和函数,B模块是无法直接访问的。

有些时候,我们写一些模块代码的时候,发现部分函数功能别人已经实现了,此时我们就想如果我们可以调用他们已经实现好的函数接口就好了。那如何才能做到这点呢?

就靠符号导出了,也就是说你可以把你实现的函数接口和全局变量导出,以供其他模块使用。

在Linux内核的世界里,如果一个模块已经以静态的方式编译进的内核,那么它导出的符号就会出现在全局的内核符号表中。

在Ubuntu 14.04系统中,Linux内核的全局符号表存放在以下文件:

/usr/src/linux-headers-3.2.0-29-generic-pae/Module.symvers

如果打开这个文件,可以发现里面的内容就是:

Addr------->符号名------>模块名------>导出符号的宏

3. 如何导出符号?

Linux内核给我们提供了两个宏:

EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);

上面宏定义的任一个使得给定的符号在模块外可用;

GPL版本的宏定义只能使符号对GPL许可的模块可用;

符号必须在模块文件的全局部分输出,在任何函数之外,因为宏定义扩展成一个特殊用途的并被期望是全局存取的变量的声明。

4. 模块编译时,如何寻找使用的符号?

  • a.在本模块中符号表中,寻找符号(函数或变量实现)
  • b.在内核全局符号表中寻找
  • c.在模块目录下的Module.symvers文件中寻找

5. 案例演示

模块A导出全局变量global_var和函数show两个符号供模块B使用。

A模块

#include <linux/init.h>
#include <linux/module.h>
static int global_var = 100;
static void show(void)
{
printk("show(): global_var =%d \n",global_var);
}
static int hello_init(void)
{
printk("module b :global_var=%d\n",global_var);
return 0;
}
static void hello_exit(void)
{
printk("hello_exit \n");
return;
}EXPORT_SYMBOL(global_var);
EXPORT_SYMBOL(show);
MODULE_AUTHOR("yikoulinux");
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);

B模块

#include <linux/init.h>
#include <linux/module.h> extern int global_var;
extern void show(void);
static int hello_init(void)
{
printk("module a: global_var= %d\n",global_var);
show();
return 0;
}
static void hello_exit(void)
{
printk("hello_exit \n");
return;
}
MODULE_AUTHOR("yikoulinux");
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);

调试步骤:

  • 1.编译模块A,然后加载模块A,在模块A编译好后,在它的当前目录会看到一个Module.symvers文件,这里存放的就是我们模块A导出的符号。
  • 2.将模块A编译生成的Module.symvers文件拷贝到模块B目录下,然后编译模块B,加载模块B。
  • 3.通过dmesg查看模块打印的信息。

    打印信息如下:



    由结果可知,我们在B模块中访问到了模块A的全局变量global_var以及函数show。

更多Linux驱动的知识,请关注公众号:一口Linux

Linux内核如何访问另外一个模块的函数和变量 原创的更多相关文章

  1. Python 包、模块、函数、变量作用域

    Python 项目的组织结构 - 包 -- 模块 --- 类 ---- 函数.变量   Python是利用包和模块来组织一个项目的.   包: 包的物理表现是一个文件夹,但是一个文件夹却不一定是个包, ...

  2. 查看Linux下*.a库文件中文件、函数、变量

    查看Linux下*.a库文件中文件.函数.变量等情况在Linux 下经常需要链接一些 *.a的库文件,那怎么查看这些*.a 中包 含哪些文件.函数.变量: 1. 查看文件:ar -t xxx.a 2. ...

  3. Python(五) 包、模块、函数与变量作用域

    一.while循环与使用场景 CONDITION=1 while CONDITION <=5 : CONDITION +=1 print("hello") else: pri ...

  4. 初探linux内核编程,参数传递以及模块间函数调用

    一.前言                                  我们一起从3个小例子来体验一下linux内核编程.如下: 1.内核编程之hello world 2.模块参数传递 3.模块间 ...

  5. Linux内核装载和启动一个可执行程序

    “平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 理解编 ...

  6. linux内核学习之二 一个精简内核的分析(基于时间片轮转)

    一   实验过程及效果 1.准备好相关的代码,分别是mymain.c,mypcb.h,myinterrupt.c ,如下图,make make成功: 在qemu创建的虚拟环境下的运行效果:(使用的命令 ...

  7. Linux内核分析:完成一个简单的时间片轮转多道程序内核代码

    PS.贺邦   原创作品转载请注明出处  <Linux内核分析>MOOC课程    http://mooc.study.163.com/course/USTC-1000029000 1.m ...

  8. Linux内核硬件访问技术

    ① 驱动程序控制设备,主要是通过访问设备内的寄存器来达到控制目的.因此我们讨论如何访问硬件,就成了如何访问这些寄存器. ② 在Linux系统中,无论是内核程序还是应用程序,都只能使用虚拟地址,而芯片手 ...

  9. linux内核中打印栈回溯信息 - dump_stack()函数分析【转】

    转自:http://blog.csdn.net/jasonchen_gbd/article/details/45585133 版权声明:本文为博主原创文章,转载请附上原博链接.   目录(?)[-] ...

  10. 使用linux内核hrtimer高精度定时器实现GPIO口模拟PWM,【原创】

    关键词:Android  linux hrtimer 蜂鸣器  等待队列 信号量 字符设备 平台信息:内核:linux3.4.39 系统:android/android5.1平台:S5P4418  作 ...

随机推荐

  1. Linux中的IDR机制

    # Linux中的IDR机制 背景 最近在学习 Linux的i2c子系统,看到代码中有关于IDR的调用.了解了一下有关的文档,发现是用来管理指针(对象实例). //based on linux V3. ...

  2. ARM 命名规则和ARM 版本

    结论:我们所接触到提到的命名规则,应该分成两类. 基于ARM Architecture版本的"指令集架构"命名规则:例如armv6, armv7, armv7s, arm64 等系 ...

  3. 浅谈k8s中cni0和docker0的关系和区别

    最近在复习k8s网络方面的知识,查看之前学习时整理的笔记和文档还有过往自己总结的博客之后发现一个问题,就是在有关flannel和calico这两个k8s网络插件的文章和博客中,会涉及到cni0和doc ...

  4. day02模板与配置

    一.WXML模板语法 1.1 数据绑定 绑定内容 跟vue差不多,在页面的js文件定义到data里面 然后通过插值语法用在wxml中即可 绑定属性 直接写上插值语法,没有: 三元运算 生成一个十以内的 ...

  5. 粗枝大叶记录一下java9模块化改造一个项目的过程(Jigsaw)

    假设项目结构如下: 其中的依赖关系为 我实际用的jdk是17 1. common模块创建描述文件,在common的src/main/java下创建module-info.java, 内容默认 /** ...

  6. 洛谷P2658

    我在洛谷第一次发个题解,管理员居然把这题的题解通道关了.... 看到好像没有优先队列的题解,来水一手 思路 形似A* 却不是A* 只需要求出其中一个点到其他点的D系数,所有D系数的最大值即是答案. 数 ...

  7. 10分钟快速掌握分布式版本控制系统GIT命令集【形成知识体系篇】

    任务要求 要求全部使用git命令实现 1.创建本地仓库,项目名称为hniu_site 2.在仓库下创建多级(目录)文件夹cn/hniu/班级名称(例如软件2108,cn/hniu/rj2108) 3. ...

  8. System.NotSupportedException:“无法显式设置 SplitterPanel 的高度。改在 SplitContainer 上设置 SplitterDistance。”

    System.NotSupportedException:"无法显式设置 SplitterPanel 的高度.改在 SplitContainer 上设置 SplitterDistance.& ...

  9. Profinet转Modbus模块减轻通讯编程工作量实现Modbus通讯

    巴图自动化PN转Modbus模块(BT-MDPN10)能够实现Profinet协议与Modbus协议之间的转换,使得Profinet协议设备与Modbus协议设备进行连接并能够相互通信. 通过使用巴图 ...

  10. 第九节 JMeter基础-高级登录【接口关联-鉴权】

    声明:本文所记录的仅本次操作学习到的知识点,其中商城IP错误,请自行更改. 背景:电商的功能:登录.加入购物车.提交订单.问题:谁把什么商品加入了购物车?这时需要把上一个接口的响应数据(登录成功后返回 ...