EXPORT_SYMBOL的作用是什么
http://www.cnblogs.com/riskyer/p/3221805.html
EXPORT_SYMBOL只出現(xiàn)在2.6內(nèi)核中,在2.4內(nèi)核默認(rèn)的非static 函數(shù)和變量都會(huì)自動(dòng)
導(dǎo)入到kernel 空間的, 都不用EXPORT_SYMBOL() 做標(biāo)記的。
2.6就必須用EXPORT_SYMBOL() 來導(dǎo)出來(因?yàn)?.6默認(rèn)不到處所有的符號(hào))。
1、EXPORT_SYMBOL的作用是什么?
EXPORT_SYMBOL標(biāo)簽內(nèi)定義的函數(shù)或者符號(hào)對(duì)全部?jī)?nèi)核代碼公開,不用修改內(nèi)核代
碼就可以在您的內(nèi)核模塊中直接調(diào)用,即使用EXPORT_SYMBOL可以將一個(gè)函數(shù)以符
號(hào)的方式導(dǎo)出給其他模塊使用。
這里要和System.map做一下對(duì)比:
System.map 中的是連接時(shí)的函數(shù)地址。連接完成以后,在2.6內(nèi)核運(yùn)行過程中,是不知道哪個(gè)符號(hào)在哪個(gè)地址的。
EXPORT_SYMBOL 的符號(hào), 是把這些符號(hào)和對(duì)應(yīng)的地址保存起來,在內(nèi)核運(yùn)行的過程中,可以找到這些符號(hào)對(duì)應(yīng)的地址。而模塊在加載過程中,其本質(zhì)就是能動(dòng)態(tài)連接到內(nèi)核,如果在模塊中引 用了內(nèi)核或其它模塊的符號(hào),就要EXPORT_SYMBOL這些符號(hào),這樣才能找到對(duì)應(yīng)的地址連接。
2、使用方法
第一、在模塊函數(shù)定義之后使用EXPORT_SYMBOL(函數(shù)名)
第二、在掉用該函數(shù)的模塊中使用extern對(duì)之聲明
第三、首先加載定義該函數(shù)的模塊,再加載調(diào)用該函數(shù)的模塊
例如:
一個(gè)模塊mod1中定義一個(gè)函數(shù)func1;
在另外一個(gè)模塊mod2中定義一個(gè)函數(shù)func2,func2調(diào)用func1。
在模塊mod1中,EXPORT_SYMBOL(func1);
在模塊mod2中,extern int func1();
就可以在mod2中調(diào)用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)注意事項(xiàng)
加載call-module.ko可能會(huì)出現(xiàn)
“NO SYMBOL VERSION FOR”問題
解決:
這是linux kernel 2.6.26 之后版本的bug (詳細(xì)描述, 請(qǐng)看http://bugzilla.kernel.org/show_bug.cgi%3Fid%3D12446)
并且這個(gè)bug不會(huì)被fix
解決辦法:
(1)mod_a的Module.symvers放到mod_b的當(dāng)前路徑,從而編譯mod_b,符號(hào)信息會(huì)自動(dòng)連接進(jìn)去.
(2)或者在mod_b的makefile中使用KBUILD_EXTRA_SYMBOLS指定mod_a的Module.symvers,
如:
KBUILD_EXTRA_SYMBOLS=/mod_a/Module.symvers
編譯mod_b時(shí),搜索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的值
問題的本質(zhì):
簡(jiǎn)單說來,就是小b生成的時(shí)候不知道小a symbol的校驗(yàn)碼,小b加載的時(shí)候自然check 校驗(yàn)碼出錯(cuò)。
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。