谈EXPORT_SYMBOL使用

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对之声明
   第三、首先加载定义该函数的模块,再加载调用该函数的模块

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

参考资料:

-------------------------------------------------------------

http://blog.chinaunix.net/u/12592/showart_461504.html

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

参考:
http://topic.csdn.net/u/20070910/09/ee2cff13-9179-41e3-9292-4fd73261f709.html
http://www.dev-archive.com/msdn-archive/524/kernel-driver-5244619.shtm

mod1.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);

static int __init hello_init(void)
{
        printk("Module 1,Init!/n");
        return 0;
}

static void __exit hello_exit(void)
{
        printk("Module 1,Exit!/n");
}

module_init(hello_init);
module_exit(hello_exit);

#############################################################
mod2.c
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/module.h>

static int func2(void)
{
        extern int func1(void);
        func1();
        printk("In Func: %s.../n",__func__);
        return 0;
}

static int __init hello_init(void)
{
        printk("Module 2,Init!/n");
        func2();
        return 0;
}

static void __exit hello_exit(void)
{
        printk("Module 2,Exit!/n");
}

module_init(hello_init);
module_exit(hello_exit);

################################################################
Makefile
ifneq ($(KERNELRELEASE),)
obj-m   := XXXX.o
else
KDIR    := /lib/modules/$(shell uname -r)/build
PWD             := $(shell pwd)

default:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

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

endif

################################################################

#insmod ./mod1.ko
#insmod ./mod2.ko
#rmmod mod2
#rmmod mod1

Jan 11 11:59:17 wangyao-desktop kernel: [ 9886.801010] Module 2,Exit!
Jan 11 11:59:21 wangyao-desktop kernel: [ 9891.450214] Module 1,Exit!
Jan 11 12:05:29 wangyao-desktop kernel: [10258.385014] Module 1,Init!
Jan 11 12:05:38 wangyao-desktop kernel: [10267.465923] Module 2,Init!
Jan 11 12:05:38 wangyao-desktop kernel: [10267.465928] In Func: func1...
Jan 11 12:05:38 wangyao-desktop kernel: [10267.465930] In Func: func2...
Jan 11 12:05:50 wangyao-desktop kernel: [10280.091755] Module 2,Exit!
Jan 11 12:05:57 wangyao-desktop kernel: [10287.332596] Module 1,Exit!

可见,在mod2中的func2函数成功的调用了mod1中的func1函数。

注意:
在编译mod2的时候,出现一个WARNING:
[email protected]:~/modules/export_symbol/mod2# make
make -C /lib/modules/2.6.22-14-generic/build SUBDIRS=/root/modules/export_symbol/mod2 modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.22-14-generic‘
  Building modules, stage 2.
  MODPOST 1 modules
WARNING: "func1" [/root/modules/export_symbol/mod2/mod2.ko] undefined!
make[1]: Leaving directory `/usr/src/linux-headers-2.6.22-14-generic‘

这主要是因为在编译连接的时候还没有和内核打交道,当然找不到symbol了,但是由于你生成的是一个内核模块,所以LD不提示error,而是给出一个warning,寄希望于在insmod的时候,内核能够把这个symbol连接上。

-----------------------------------------------------------

http://www.lslnet.com/linux/f/docs1/i46/big5316526.htm

請教關於EXPORT_SYMBOL

在一個文件裡要用到別的文件中的函數 用extern不就可以了麼

為什麼還需要EXPORT_SYMBOL

謝謝

Re: 請教關於EXPORT_SYMBOL

EXPORT_SYMBOL是給模塊用的。

Re: 請教關於EXPORT_SYMBOL

我看好像只要函數不是聲明為static的
在System.map中也有並且和EXPORT_SYMBOL的函數一樣。

模塊也可以使用的吧

Re: 請教關於EXPORT_SYMBOL

System.map 中的是鏈接時的函數地址。 連接完成以後,在內核運行過程中,是不知道哪個符號在那個地址的。而這個文件是給調試用的。其中的內容,kernel並不知道 。

EXPORT_SYMBOL 的符號, 是把這些符號和對應的地址,保存起來,在內核運行的過程中,可以找到這些符號對應的地址的。

而module在加載過程中,其本質就是動態連接到內核,如果在模塊中引用了內核或其它模塊的符號,就要 EXPORT_SYMBOL 這些符號,這樣才能找到對應的地址連接呀。 要不沒法連接的

Re: 請教關於EXPORT_SYMBOL

那個是2.4的, 2.4中只要全局的, 符號就算導出了; 2.6則必須顯式調用EXPORT_SYMBOL或其變體。

Re: 請教關於EXPORT_SYMBOL

內核模塊加載的鏈接過程,不是一個普通的鏈接過程,是內核自己做的一個特殊的過程,
因此,單純extern是不可以的,內核強行要求用EXPORT_SYMBOL

-------------------------------------------------------------

http://hi.baidu.com/leal/blog/item/d3e1cafcb97c2dfdfd037fc2.html

System.map[1]是Linux内核符号文件,维护有内核函数名称和非堆栈变量名称与各自地址的对应关系。

若内核函数或变量要被内核模块调用,则必须使用EXPORT_SYMBOL宏进行处理,作用之一是将该符号连接到二进制文件的各个 __ksymtab_xx_xx section(参看include/linux/module.h,使用GCC编译器的__attribute__关键字实现[2])。内核加载模块 时,会先确认该模块调用的各内核函数是否已export(参看__find_symbol() kernel/module.c)。

比如FC5缺省会给vanilla内核打补丁,使其不再export sys_open符号,这一点可搜索该内核对应的System.map文件进行确认,看是否存在__ksymtab_sys_open符号。

[1] The system.map File
http://www.dirac.org/linux/system.map/

[2] Using GNU C __attribute__
http://www.unixwiz.net/techtips/gnu-c-attributes.html

------------------------------------------------------------

http://www.linuxsir.org/bbs/thread347677.html

在编写module是,如果函数的声明没有加static,那么我理解就应该是全局的阿,没什么要用
EXPORT_SYMBOL()

好象是因为系统需要生成类似于C00021_PRINTK 一类的链接用的,因为系统的函数本身其实是有其前缀的

模块是动态加载的,需要一个运行时存在的符号表,找到符号。而我们一般所说的符号表是供静态连接时定位符号地址用的。EXPORT_SYMBOL宏的作用就是把静态符号表中的符号和地址放到运行时的符号表中(在一个section中)供运行时寻找符号用
看一下EXPORT_SYMBOL的定义就知道了。

-------------------------------------------------------------

http://www.unixresources.net/linux/clf/linuxK/archive/00/00/71/60/716080.html

driver/char/console.c 里面提供了 这个函数:

/* console_sem is held (except via vc_init()) */

void reset_terminal(int currcons, int do_clear)

{

top		= 0;

bottom		= video_num_lines;

。。。。。。

在console.c 的最后面也有:

/* 
* Visible symbols for modules 
*/

EXPORT_SYMBOL(fg_console); 
EXPORT_SYMBOL(console_blank_hook); 
EXPORT_SYMBOL(hide_cursor); 
EXPORT_SYMBOL(reset_terminal); //这个

drivers/char/Makefile 里面也有:

# All of the (potential) objects that export symbols.

# This list comes from ‘grep -l EXPORT_SYMBOL *.[hc]‘.

export-objs     :=	busmouse.o console.o keyboard.o sysrq.o 

misc.o pty.o random.o selection.o serial.o 

sonypi.o tty_io.o tty_ioctl.o generic_serial.o 

au1000_gpio.o hp_psaux.o nvram.o scx200.o

我要在kernel/power/ui.c 里面调用:

void pm_restore_console(void)

{

if (TEST_ACTION_STATE(SUSPEND_NO_OUTPUT))

return;

//	reset_terminal(suspend_console, 1);

reset_terminal(TTY_MAJOR,1);

可是编译内核的时候, 最后, 就说 undefined reset_terminal () , 奇怪了。

/usr/bin/mips-linux-ld -G 0 -static -T arch/mips/ld.script arch/mips/kernel/head.o 
arch/mips/kernel/init_task.o init/main.o init/version.o init/do_mounts.o --start-group 
arch/mips/kernel/kernel.o arch/mips/mm/mm.o kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o 
arch/mips/math-emu/fpu_emulator.o arch/mips/emma2_se/emma2.o drivers/char/char.o 
drivers/block/block.o drivers/misc/misc.o drivers/net/net.o drivers/ide/idedriver.o 
drivers/pci/driver.o drivers/mtd/mtdlink.o drivers/net/wireless/wireless_net.o 
drivers/usb/usbdrv.o drivers/media/media.o drivers/md/mddev.o net/network.o 
arch/mips/lib/lib.a /home/work/data3/standby/dv_kernel_suspend2/linux/lib/lib.a 
--end-group -o vmlinux 
kernel/kernel.o: In function `pm_restore_console‘: 
kernel/kernel.o(.text+0x16030): undefined reference to `reset_terminal‘ 
kernel/kernel.o(.text+0x16030): relocation truncated to fit: R_MIPS_26 reset_terminal 
make[1]: *** [kallsyms] Error 1 
make[1]: Leaving directory `/home/work/data3/standby/dv_kernel_suspend2/linux‘ 
make: *** [vmlinux] Error 2

大家帮诊断一下。 -DEXPORT_SYMTAB 我也加了。 还是不行。

EXPORT_SYMBOL()
被export的符号,是用来给加载模块时链接时用的, 编译内核自身时, 和export 应该是没有关系的. 看是否包含了对应的头文件, console.c是被编译为模块, 还是编译到内核? 如果是别编译到内核, 只要在ui.c 
里包含了定义reset_terminal的头文件,应该是可以编译出来的.

没错,一阵见血。
找到原因了,console.o 的编译被我们自己的宏给包住了(我们自己改了一些东西), 结果 console.o 没有被编译出来,当然就找不到reset_terminal() 了。
所以光有:
export-objs := busmouse.o console.o keyboard.o sysrq.o
misc.o pty.o random.o selection.o serial.o
sonypi.o tty_io.o tty_ioctl.o generic_serial.o
au1000_gpio.o hp_psaux.o nvram.o scx200.o
也是不行的,
还有了一个 obj-y =+ console.o

我补充一下:
以前做2.4的时候确实如此,
我记得是 对于2.4 来说, 默认的非static 函数和变量都会自动导入到kernel 空间的, 都不用EXPORT_SYMBOL() 做标记的。

2.6就必须用EXPORT_SYMBOL() 来导出来(因为2.6默认不到处所有的符号)。

-----------------------------------------------------------

http://forum.kernelnewbies.org/read.php?12,153

时间: 2024-10-01 06:53:34

谈EXPORT_SYMBOL使用的相关文章

Linux进程管理简谈

Linux系统进程管理简谈 进程是什么? 简单来说进程是一个正在执行的程序的一个副本,存在生命周期,有段指令和代码在不断运行. linux内核存储信息的固定格式:task struct 进程的相关信息存储在链表中 多个任务的task struct组件的链表:task list 进程的创建:父进程创建子进程(内核创建init进程,剩余一切进程有init及其子进程进程创建) 父进程创建子进程时向内核调用fork()来创建子进程并且通过调用clone()复制父进程的信息给子进程 Linux进程的优先级

.net中对象序列化技术浅谈

.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数 据.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象.反之,反序列化根据流重新构造对象.此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件 中“恢复”对象到序列化之前的状态.在.net中有提供了几种序列化的方式:二进制序列化

浅谈JavaScript中继承的实现

  谈到js中的面向对象编程,都有一个共同点,选择原型属性还是构造函数,两者各有利弊,而就片面的从js的对象创建以及继承的实现两个方面来说,官方所推荐的是两个相结合,各尽其责,各取其长,在前面的例子中,我已就在JavaScript中对象创建的方法做了一些总结,下面就其继承来道说一二:   1:原型链继承: 每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象内部的指针(默认的原型,所有默认类型都继承了Object,而这个继承也是用过原型链实现) fu

运维角度浅谈:MySQL数据库优化

日志君导读: 一个成熟的数据库架构并不是一开始设计就具备高可用.高伸缩等特性的,它是随着用户量的增加,基础架构才逐渐完善. 作者:zhenliang8,本文转自51CTO博客,点击原文阅读查看网页版文章. 本博文主要谈MySQL数据库发展周期中所面临的问题及优化方案,暂且抛开前端应用不说,大致分为以下五个阶段: 1.数据库表设计 项目立项后,开发部根据产品部需求开发项目,开发工程师工作其中一部分就是对表结构设计.对于数据库来说,这点很重要,如果设计不当,会直接影响访问速度和用户体验.影响的因素很

浅谈——页面静态化

现在互联网发展越来越迅速,对网站的性能要求越来越高,也就是如何应对高并发量.像12306需要应付上亿人同时来抢票,淘宝双十一--所以,如何提高网站的性能,是做网站都需要考虑的. 首先网站性能优化的方面有很多:1,使用缓存,最传统的一级二级缓存:2,将服务和数据库分开,使用不同的服务器,分工更加明确,效率更加高:3,分布式,提供多台服务器,利用反向代理服务器nginx进行反向代理,将请求分散开来:4,数据库的读写分离,不同的数据库,将读操作和写操作分开,并实时同步即可:5,分布式缓存,使用memc

从Trie谈到AC自动机

ZJOI的SAM让我深受打击,WJZ大神怒D陈老师之T3是SAM裸题orz...我还怎么混?暂且写篇`从Trie谈到AC自动机`骗骗经验. Trie Trie是一种好玩的数据结构.它的每个结点存的是字母,因此得名`字母树`. 出一张图让大家感受下. (image powered by SaiBu NaoCu) 上面那是一棵插入了 ape,app,applicant,application,bake,ban,banana 等词的Trie.红色结点表示接受态. 显然,查找时只需顺着链照下来,插入只需

【云杂谈】之二《AT&T发布基于云存储的物联网产品》

2015-01-14张晓东东方云洞察 点击上面的链接文字,可以快速关注"东方云洞察"公众号 AT&T建立了基于云数据存储的物联网产品 近日AT&T宣布了新的设计工具和基于企业的开发管理服务,帮助企业开发者构建物联网(IOT)的应用程序和服务. 新的AT&T M2X数据服务是一种基于云的数据存储,其目的是使连接到大型企业遥远设备,更容易进行数据收集和分析数据. 相应的测试该服务去年推出,AT&T官员表示,在其年度开发者峰会刚刚举行的国际消费电子展之前在这里

单页应用SEO浅谈

单页应用SEO浅谈 前言 单页应用(Single Page Application)越来越受web开发者欢迎,单页应用的体验可以模拟原生应用,一次开发,多端兼容.单页应用并不是一个全新发明的技术,而是随着互联网的发展,满足用户体验的一种综合技术. SEO 一直以来,搜索引擎优化(SEO)是开发者容易忽略的部分.SEO是针对搜索(Google.百度.雅虎搜索等)在技术细节上的优化,例如语义.搜索关键词与内容相关性.收录量.搜索排名等.SEO也是同行.市场竞争常用的的营销手段.Google.百度的搜

浅谈Spring(二)IOC原理

一.引言 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑.举例:如果我们打开机械式手表的后盖,就会发现其是由N个齿轮组成,各个齿轮分别带动时针.分针和秒针顺时针旋转,从而在表盘上产生正确的时间.在这样的齿轮组中,如果有一个齿轮出了问题,就可能会影响到整个齿轮组的正常运转.齿轮组中齿轮之间的啮合关系,与软件系统中对象之间的耦合关系非常相似.对象之间的耦合关系是无法避免的,也是必要的,这是协同工作的基础.现在,伴随着