一、问题整理

内核中两个模块,一个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. 2019 香港区域赛 BDEG 题解

    B.Binary Tree 题意:给你一棵二叉树.有两个游戏者,回合制,他们每次可以删去这棵二叉树中的一棵满二叉树.求最后谁赢. 解法:每一棵满二叉树有奇数个节点,那么每次游戏者只能删去奇数个节点,所 ...

  2. PetaLinux常用命令汇总

    创建petalinux工程 Create a new project from a reference BSP file. 用于从官方下载的BSP中抽取数据产生工程. petalinux-create ...

  3. STM32 CubeMX 学习:06-配置DMA

    --- title: mcu-stm32-cube-06-配置DMA date: 2020-05-31 16:39:05 categories: tags: - stm32 - cubeMx - dm ...

  4. C#语言编写的仅有8KB大小的简易贪吃蛇开源游戏

    前言 今天大姚给大家分享一款由C#语言编写的仅有8KB大小的简易贪吃蛇开源游戏:SeeSharpSnake. 项目特点 该仓库中的项目文件和脚本可以用多种不同的配置构建相同的游戏,每个配置生成的输出大 ...

  5. tcp_tw_reuse、tcp_tw_recycle、tcp_fin_timeout参数介绍

    参数介绍 net.ipv4.tcp_tw_reuse = 1 表示开启重用.允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭: net.ipv4.tcp_tw_rec ...

  6. 【Hive报错】在hue上执行自定义的hive函数报错 Error while compiling statement:FAILED:SemanticException [Error 10011]: Invalid function default.sqlServerdes

    在 Hive客户端中使用自定义创建UDF函数时,报"ERROR 10011","invalid function"的异常: 在Hive上自定义创建了一个函数,在 ...

  7. 运行前端React框架出现node Error: bind EADDRINUSE null的解决方法

    运行前端React代码时,出现这样的错误: node Error: bind EADDRINUSE null 后来发现端口号冲突,换个端口号后问题就可以解决了.

  8. oeasy教您玩转vim - 49 - # 命令进阶

    ​ 命令进阶 回忆上节课内容 我们上次研究vim的历史 为什么会有行编辑器这种东西 竟然是当年 没有显示器只有纸的时代的无奈之举 vim进化到今天 依然还有好多人使用 而且ssh连接的时候直接vim就 ...

  9. 涨见识了!脱离vue项目竟然也可以使用响应式API

    前言 vue3的响应式API大家应该都特别熟悉,比如ref.watch.watchEffect等.平时大家都是在vue-cli或者vite创建的vue项目里面使用的这些响应式API,今天欧阳给大家带来 ...

  10. VScode配置PHP开发环境

    vscode配置php开发环境 使用vscode配置PHP开发环境,首先要下载vscode, vscode下载 下载完vscode之后,可以在扩展里面下载中文版本 将vscode下载完之后,需要下载x ...