温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Linux内核怎样访问另外一个模块的函数和变量

发布时间:2021-09-27 17:48:52 来源:亿速云 阅读:156 作者:柒染 栏目:系统运维

今天就跟大家聊聊有关Linux内核怎样访问另外一个模块的函数和变量,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

一、问题整理

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

Linux内核怎样访问另外一个模块的函数和变量

二、分析

这是一个驱动工程师经常遇到的一个问题,该问题其实是模块符号导出问题,实现该功能比较简单,借助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------->符号名------>模块名------>导出符号的宏

 Linux内核怎样访问另外一个模块的函数和变量

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查看模块打印的信息。打印信息如下:

Linux内核怎样访问另外一个模块的函数和变量

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

看完上述内容,你们对Linux内核怎样访问另外一个模块的函数和变量有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI