標籤:
轉自:http://blog.chinaunix.net/uid-23381466-id-3837650.html
核心版本: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.
driver: linux2.6 核心模組匯出函數執行個體(EXPORT_SYMBOL) 【轉】