专栏中心

EEPW首页 > 专栏 > EXPORT_SYMBOL的作用是什么

EXPORT_SYMBOL的作用是什么

发布人:电子禅石 时间:2020-12-11 来源:工程师 发布文章

http://www.cnblogs.com/riskyer/p/3221805.html

 

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这些符号,这样才能找到对应的地址连接。

2、使用方法
第一、在模块函数定义之后使用EXPORT_SYMBOL(函数名)
第二、在掉用该函数的模块中使用extern对之声明

第三、首先加载定义该函数的模块,再加载调用该函数的模块


例如:

一个模块mod1中定义一个函数func1;

在另外一个模块mod2中定义一个函数func2,func2调用func1。

在模块mod1中,EXPORT_SYMBOL(func1);

在模块mod2中,extern int func1();

就可以在mod2中调用func1了。


(1)helloworld.c

 

#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");

static void hello_fun(void)
{
  printk("##### helloworld####\n");
}
EXPORT_SYMBOL(hello_fun);

static int __init hello_init(void)
{
   printk(KERN_ERR "#### hello world\n");
   return 0;
}

static void __exit hello_exit(void)
{
   printk(KERN_ERR "#### exit\n");
}

module_init(hello_init);
module_exit(hello_exit);

 


Makefile

 

obj-m := hello.o
hello-objs := helloworld.o

KID := /lib/modules/`uname -r`/build
PWD := $(shell pwd)

all:
	make -C $(KID) M=${PWD} modules

clean:
	rm -rf *.o .cmd *.ko *.mod.c .tmp_versions


 


(2)call-module.c

 

#include <linux/module.h>
#include <linux/init.h>

extern void hello_fun(void);

static int __init hello_init(void)
{
   hello_fun();
   return 0;
}

static void __exit hello_exit(void)
{
   printk(KERN_ERR "#### exit\n");
}

MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);


Makefile

 

 

obj-m := call-module.o

KID := /lib/modules/`uname -r`/build
PWD := $(shell pwd)
KBUILD_EXTRA_SYMBOLS=/usr/src/linux-headers-3.5.0-34-generic/Module.symvers

KBUILD_EXTRA_SYMBOLS +=/home/snail/work/2.linux-driver/1.helloworld/Module.symvers

all:
	make -C $(KID) M=${PWD} modules

clean:
	rm -rf *.o .cmd *.ko *.mod.c .tmp_versions *.order *.symvers .*


(3)

 

加载 hello.ko

sudo insmod ./hello.ko


加载 call-module.ko 

sudo insmod ./call-module.ko 


观察 dmesg

<4>[ 3837.857657] ##### helloworld####


(4)注意事项

加载call-module.ko可能会出现

“NO SYMBOL VERSION FOR”问题


解决:


这是linux kernel 2.6.26 之后版本的bug (详细描述, 请看http://bugzilla.kernel.org/show_bug.cgi%3Fid%3D12446)
并且这个bug不会被fix
解决办法:

(1)mod_a的Module.symvers放到mod_b的当前路径,从而编译mod_b,符号信息会自动连接进去.
(2)或者在mod_b的makefile中使用KBUILD_EXTRA_SYMBOLS指定mod_a的Module.symvers,

 如:
KBUILD_EXTRA_SYMBOLS=/mod_a/Module.symvers
编译mod_b时,搜索Module.symvers的路径是:
1, kernel source path, e.g. /usr/src/kernels/linux-2.6.28.10
2, makefile中M=所指定的路径, 它等效于变量KBUILD_EXTMOD的值
3, 变量KBUILD_EXTRA_SYMBOLS的值

问题的本质:
简单说来,就是小b生成的时候不知道小a symbol的校验码,小b加载的时候自然check 校验码出错。


专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们

关键词:

相关推荐

Pat Gelsinger告诫陈立武“华尔街的短期主义”

高通在全球范围内指控 Arm垄断反竞争,芯片架构授权模式面临重构

基于ARM7的智能行动辅助专家

视频 2009-11-16

苹果全球开发者大会WWDC25官宣6月10日开幕

康普发布面向数据中心的Propel XFrame解决方案

应用于健康手机的高性能生物电信号采集模块

视频 2009-11-16

汽车安全完整性等级 (ASIL) 指南

新版DeepSeek V3悄然发布 外媒:很强但少了\"人味\"

高强度放电(HID)灯电子镇流器设计

视频 2009-11-16

用于电动汽车车载充电器的CLLLC与DAB比较

瑞萨电子推出全新低功耗蓝牙SoC,为车载应用带来更低能耗

智能迎宾机器人的设计与实现

视频 2009-11-16

Gartner发布2025年数据和分析重要趋势

基于LPC3250之一种海浪能发电系统

视频 2009-11-16

Littelfuse推出通过AEC-Q200认证的823A系列高压汽车应用保险丝

更多 培训课堂
更多 焦点
更多 视频

技术专区