EXPORT_SYMBOL使用

EXPORT_SYMBOL使用EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static函数和变量都会自动导入到kernel空间的,都不用EXPORT_SYMBOL()做标记的。2.6就必须用EXPO

大家好,又见面了,我是你们的朋友全栈君。

EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static 函数和变量都会自动导入到kernel 空间的, 都不用EXPORT_SYMBOL() 做标记的。
2.6就必须用EXPORT_SYMBOL() 来导出来(因为2.6默认不到处所有的符号)。 

1、EXPORT_SYMBOL的作用
EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。

这里要和System.map做一下对比:
System.map 中的是连接时的函数地址。连接完成以后,在2.6内核运行过程中,是不知道哪个符号在哪个地址的。
EXPORT_SYMBOL 的符号, 是把这些符号和对应的地址保存起来,在内核运行的过程中,可以找到这些符号对应的地址。

而模块在加载过程中,其本质就是能动态连接到内核,如果在模块中引用了内核或其它模块的符号,就要EXPORT_SYMBOL这些符号,这样才能找到对应的地址连接。

使用方法:

   第一、在模块函数定义之后使用EXPORT_SYMBOL(函数名)
   第二、在掉用该函数的模块中使用extern对之声明
   第三、首先加载定义该函数的模块,再加载调用该函数的模块

另外,在编译调用某导出函数的模块时,往往会有WARNING: “****” [**********] undefined!
使用dmesg命令后会看到相同的信息。开始我以为只要有这个错误就不能加载模块,后来上网查了一下,发现这主要是因为在编译连接的时候还没有和内核打交道,当然找不到symbol了,但是由于你生成的是一个内核模块,所以LD不提示error,而是给出一个warning,寄希望于在insmod的时候,内核能够把这个symbol连接上。

一个模块mod1中定义一个函数func1;在另外一个模块mod2中定义一个函数func2,func2调用func1。
在模块mod1中,EXPORT_SYMBOL(func1);
在模块mod2中,extern int func1();
就可以在mod2中调用func1了

EXPORT_SYMBOL示范

比如有两个驱动模块:Module A和Module B,其中Module B使用了Module A中的export的函数,因此在Module B的Makefile文件中必须添加:

KBUILD_EXTRA_SYMBOLS += /path/to/ModuleA/Module.symvers

export KBUILD_EXTRA_SYMBOLS

这样在编译Module B时,才不会出现Warning,提示说func1这个符号找不到,而导致编译得到的ko加载时也会出错。

// Module A (mod_a.c)  
#include<linux/init.h>  
#include<linux/module.h>  
#include<linux/kernel.h>  
  
static int func1(void)  
{  
       printk("In Func: %s...\n",__func__);  
       return 0;  
}  
  
// Export symbol func1  
EXPORT_SYMBOL(func1);  
  
static int __init hello_init(void)  
{  
       printk("Module 1,say hello world!\n");  
       return 0;  
}  
  
static void __exit hello_exit(void)  
{  
       printk("Module 1,Exit!\n");  
}  
  
module_init(hello_init);  
module_exit(hello_exit);  
// Module B (mod_b.c)  
#include<linux/init.h>  
#include<linux/kernel.h>  
#include<linux/module.h>  
extern int functl(void);  
static int func2(void)  
{  
       func1();  
       printk("In Func: %s...\n",__func__);  
       return 0;  
}  
  
static int __init hello_init(void)  
{  
       printk("Module 2,is used Module 1 function!\n");  
       func2();  
       return 0;  
}  
  
static void __exit hello_exit(void)  
{  
       printk("Module 2,Exit!\n");  
}  
  
module_init(hello_init);  
module_exit(hello_exit);  
在驱动加载的时候,一定要先加载定义function1的Module A模块,然后再加载调用function1的Module B的驱动模块。
如下操作:
insmod Module_A.ko  
insmod Module_B.ko  

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/154295.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JavaWeb总结–Servlet 工作原理解析

    JavaWeb总结–Servlet 工作原理解析

    2021年9月16日
    45
  • mysql 左连接 自连接 例子

    mysql 左连接 自连接 例子连接就是将两个表按照某个公共字段来拼成一个大表。左连接就是在做连接是以左边这个表为标准,来遍历右边的表。例子:用户访问记录:问题:查出看了湖南卫视但没有看北京卫视的用户信息逻辑:先通过左连接将看了湖南卫视和北京卫视的查出来,然后再将看了湖南卫视但不在刚才查出的结果中的用户查出来。SELECT*FROMtest_visitWHEREchannel=’

    2022年5月28日
    29
  • 转:谷歌离线地图基础[通俗易懂]

    转:谷歌离线地图基础[通俗易懂]一.需要文件gapi3文件夹:存放接口等tilemap文件夹:存放图片gapi.js文件maptool.js文件二.html配置&lt;scripttype="text/javascript"src="gapi.js"&gt;&lt;/script&gt;&lt;scripttype="text/javascript"src="maptool.js"&gt;&lt

    2022年9月20日
    1
  • python-列表(list)使用方法

    python-列表(list)使用方法这篇文章主要整理和记录python中列表(list)的使用方法,适合像我一样初学python的朋友们哟!List是一个有序的、可重复的数据类型,可以对其元素进行添加、删除、修改等操作。List支持

    2022年7月3日
    30
  • 【《重构 改善既有代码的设计》学习笔记4】构筑测试体系

    本篇文章的内容来自《重构 改善既有代码的设计》一书学习笔记整理并且加上自己的浅显的思考总结!如果想要进行重构,首要前提是 拥有一个可靠的测试环境。1、 自测代码的价值完成一个功能:设计+开发+调试,认真分析,程序员最多花费的时间不是开发(编码),而是用来调试。调试可能花费无数个小时,甚至通宵达旦。修复错误是快速的,而找出错误却是恶梦一场。当修复好一个错误,总是会有另一个错误的出现。而引…

    2022年2月27日
    43
  • stm32l476芯片介绍(nvidia驱动无法找到兼容的图形硬件)

    前言最近购买了IoTBoard潘多拉开发板来研究,学习使用STM32CubeMX工具配置SPI,然后驱动了TFTLCD。潘多拉开发板的TFTLCD驱动IC是ST7789V2,结合原子哥的TFTLCD代码,分享自己的硬件SPI+软件SPI驱动ST7789V2+中文显示。关于STM32CubeMX的使用可以参考微雪课堂STM32CubeMX系列教程。STM32L475硬件SPI+软…

    2022年4月17日
    99

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号