內核版本:2.6.38-11-generic
????內核自己都大量利用內核符號表導出函數,那么應該導出呢,ldd3上面說只需要EXPORT_SYMBOL一類的宏導出即可,結果試了很久都不行,最后查看文檔,算是明白一點了。
????對于導出符號表,內核文檔給出了三種解決方案,見尾部,現在忽略。
????現在有兩個模塊,a模塊導出函數myprint,b模塊使用該函數,想象一下如果a模塊 EXPORT_SYMBOL(myprint) ,實際上b模塊知道嗎,很明顯b模塊對這件事情不是很清楚(這么說不是很準確),要調用a模塊的myprint函數,需要知道myprint函數在內存中的位置,首先在內核符號表中是沒有說明的,所以...
????當我們編譯完a模塊后,看看有些什么文件,是不是有一個Module.symvers文件,打開看看什么狀況?
0x705034f7????myprint????/home/darren/Desktop/darren/print/myprint????EXPORT_SYMBOL
好了,這一行對b模塊來說已經足夠了,指定了內存位置,符號名稱,模塊路徑。最簡單的方法就是把這個文件復制到b模塊所在目錄,然后編譯就沒有討厭的錯誤了,可以正常insmod模塊。這種方法是內核文檔中提到的方法之一。
????但是每次調用該函數都要復制一次,更糟糕的是a模塊每編譯一次,都要重新復制一次,為什么內核自己導出的函數我們可以直接用呢?現在就就解決:
????編譯內核的時候同樣會生成一個Module.symvers文件,內核導出的所有符號都在里面,我們在編譯模塊的時候實際上會調用內核的頂層makefile,也就是說內核的Module.symvers對我們的模塊是可見的,和我們自己的Module.symvers文件一樣,OK,把a模塊的Module.symvers文件合并到內核的Module.symvers文件中,這時候myprint函數就成了真正的導出函數了,其他的模塊只需要生命一下就可以用了。
代碼如下
a模塊代碼:
點擊(此處)折疊或打開
#include?<linux/module.h>
#include?<linux/init.h>
#include?<linux/kernel.h>?
MODULE_LICENSE("GPL");
int?myprint(void)
{
????printk("c");
????return 0;
}
static?int?darren_init(void)
{
????return 0;
}
static void darren_exit(void)
{
}
module_init(darren_init);
module_exit(darren_exit);
EXPORT_SYMBOL(myprint); b模塊代碼: 點擊(此處)折疊或打開
#include?<linux/seq_file.h>
#include?<linux/cdev.h>
#include?<asm/system.h>?
MODULE_LICENSE("GPL");
extern?int?print(void);
static?int?darren_init(void)
{
????int?i=0;
????printk("b module init\n");
????for(;i<10;i++)print();
????return 0;
}
static void darren_exit(void)
{
}
module_init(darren_init);
module_exit(darren_exit); a模塊的Makefile如下: 點擊(此處)折疊或打開 NAME:=a
SYM:=/usr/src/linux-headers-2.6.38-8-generic/Module.symvers
DIR:=/lib/modules/$(shell uname?-r)/build/
PWD:=$(shell pwd)
obj-m?=?$(NAME).o
build:?
????
????make?-C $(DIR)?M=$(PWD)
????sudo chmod 777 $(SYM)
????sudo sed?-i?'/myprint/d'?$(SYM)
????sudo cat Module.symvers>>$(SYM)
????sudo chmod 644 $(SYM) b模塊的makefile: 點擊(此處)折疊或打開 NAME:=b
DIR:=/lib/modules/$(shell uname?-r)/build/
PWD:=$(shell pwd)
obj-m?=?$(NAME).o
build:?
????make?-C $(DIR)?M=$(PWD) 注意:路徑/usr/src/linux-headers-2.6.38-8-generic/Module.symvers 有可能不對如果不行就改成/usr/src/linux-headers-`uname -r`-generic/Module.symvers 內核文檔: 點擊(此處)折疊或打開
Sometimes,?an external module?uses?exported symbols from
????another external module.?kbuild needs to have full knowledge?of
????all symbols to avoid spitting?out?warnings about undefined
????symbols.?Three solutions exist?for?this?situation.
????NOTE:?The method with a top-level kbuild file is recommended
????but may be impractical?in?certain situations.
????Use a top-level kbuild file
????????If?you have two modules,?foo.ko?and?bar.ko,?where
????????foo.ko needs symbols from bar.ko,?you can use a
????????common top-level kbuild file so both modules are
????????compiled?in?the same build.?Consider the following
????????directory layout:
????????./foo/?<=?contains foo.ko
????????./bar/?<=?contains bar.ko
????????The top-level kbuild file would then look like:
????????#./Kbuild?(or?./Makefile):
????????????obj-y?:=?foo/ bar/
????????And?executing
????????????$ make?-C $KDIR M=$PWD
????????will then do the expected?and?compile both modules with
????????full knowledge?of?symbols from either module.
????Use an extra Module.symvers file
????????When an external module is built,?a Module.symvers file
????????is generated containing all exported symbols which are
????????not?defined?in?the kernel.?To get access to symbols
????????from bar.ko,?copy the Module.symvers file from the
????????compilation?of?bar.ko to the directory where foo.ko is
????????built.?During the module build,?kbuild will read the
????????Module.symvers file?in?the directory?of?the external
????????module,?and?when the build is finished,?a new
????????Module.symvers file is created containing the sum?of
????????all symbols defined?and?not?part?of?the kernel.
????Use?"make"?variable KBUILD_EXTRA_SYMBOLS
????????If?it is impractical to copy Module.symvers from
????????another module,?you can assign a space separated list
????????of?files to KBUILD_EXTRA_SYMBOLS?in?your build file.
????????These files will be loaded by modpost during the
????????initialization?of?its symbol tables.
頂
0 踩
總結
以上是生活随笔為你收集整理的driver: linux2.6 内核模块导出函数实例(EXPORT_SYMBOL)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。