Makefile 裏添加:
KBUILD_EXTRA_SYMBOLS += /home/peng/omapl138/module/a/Module.symvers
export KBUILD_EXTRA_SYMBOLS
否則出現unknow symbol . version等錯誤
------------------------------------------------------------------------------------------------------------------------------------------------
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:
root@wangyao-desktop:~/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
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/macrossdzh/archive/2009/09/28/4601648.aspx