EXPORT_SYMBOL的作用是什么


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 校驗碼出錯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM