一般我們編寫C程序時(shí),要調(diào)用某個(gè)文件中的函數(shù),需要在本文件中包含聲明有被調(diào)用函數(shù)的頭文件,然后編譯連接后,方能找到調(diào)用函數(shù)。對(duì)于模塊依賴的情況,不能簡(jiǎn)單的使用上面的方法,內(nèi)核提供了一個(gè)機(jī)制,就是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)出給其他模塊使用 。 您還可以手工修改內(nèi)核源代碼來導(dǎo)出另外的函數(shù),用于重新編譯并加載新內(nèi)核后的測(cè)試。
?
include/module.h: struct kernel_symbol { unsigned long value; const char *name; }; /* For every exported symbol, place a struct in the __ksymtab section */ #define __EXPORT_SYMBOL(sym, sec) \ __CRC_SYMBOL(sym, sec) \ static const char __kstrtab_##sym[] \ __attribute__((section("__ksymtab_strings"))) \ = MODULE_SYMBOL_PREFIX #sym; \ static const struct kernel_symbol __ksymtab_##sym \ __attribute_used__ \ __attribute__((section("__ksymtab" sec), unused)) \ = { (unsigned long)&sym, __kstrtab_##sym } #define EXPORT_SYMBOL(sym) \ __EXPORT_SYMBOL(sym, "") #define EXPORT_SYMBOL_GPL(sym) \ __EXPORT_SYMBOL(sym, "_gpl") #endif
?
下面是這種方法是演示:
第一個(gè)模塊文件如下:
[lingyun@localhost export_symbol]$ ls
mod1 ?mod2
[lingyun@localhost export_symbol]$ cd mod1/
[lingyun@localhost mod1]$ ls
Makefile ?mod_a.c
[lingyun@localhost mod1]$ vim mod_a.c?
?mod_a.c ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
/********************************************************************************* * Copyright: (C) 2013 fulinux<fulinux@sina.com> * All rights reserved. * * Filename: mod_a.c * Description: This file * * Version: 1.0.0(07/12/2013~) * Author: fulinux <fulinux@sina.com> * ChangeLog: 1, Release initial version on "07/12/2013 10:06:50 AM" * ********************************************************************************/ #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); MODULE_LICENSE("GPL");
其中EXPORT_SYMBOL(func1)導(dǎo)出func1函數(shù)符號(hào),保存函數(shù)地址和名稱.
?
這個(gè)模塊的第一個(gè)Makefile文件:
[lingyun@localhost mod1]$ ls
Makefile ?mod_a.c
[lingyun@localhost mod1]$ vim Makefile?
?
obj-m:=mod1.o mod1-y:=mod_a.o KERNELDIR := /lib/modules/$(shell uname -r)/build PWD:=$(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~core .depend .*.cmd *.ko *.ko.* *.mod.c .tmp_versions *odule* $(TARGET)
其中
內(nèi)嵌對(duì)象 - obj-y,可加載模塊 - obj-m,
KERNELDIR指向
指向內(nèi)核代碼目錄。
?
編譯編譯并加載:
[lingyun@localhost mod1]$ ls
Makefile ?mod_a.c
[lingyun@localhost mod1]$ make
make -C /lib/modules/2.6.32-279.el6.x86_64/build ?M=/usr/local/src/lingyun/fulinux/export_symbol/mod1 modules
make[1]: Entering directory `/usr/src/kernels/2.6.32-279.el6.x86_64'
? CC [M] ?/usr/local/src/lingyun/fulinux/export_symbol/mod1/mod_a.o
? LD [M] ?/usr/local/src/lingyun/fulinux/export_symbol/mod1/mod1.o
? Building modules, stage 2.
? MODPOST 1 modules
? CC ? ? ?/usr/local/src/lingyun/fulinux/export_symbol/mod1/mod1.mod.o
? LD [M] ?/usr/local/src/lingyun/fulinux/export_symbol/mod1/mod1.ko.unsigned
? NO SIGN [M] /usr/local/src/lingyun/fulinux/export_symbol/mod1/mod1.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.32-279.el6.x86_64'
[lingyun@localhost mod1]$ sudo insmod mod1.ko
[lingyun@localhost mod1]$ cat /proc/kallsyms | grep func1
0000000000000000 r __
ksymtab_func1
? ? ?[mod1]
0000000000000000 r __
kstrtab_func1
? ? ?[mod1]
0000000000000000 r __
kcrctab_func1
? ? ?[mod1]
0000000000000000 T func1 ? ? ? ?[mod1]
[lingyun@localhost mod1]$?
[lingyun@localhost mod1]$ dmesg | grep Module
- User ID: CentOS (Kernel Module GPG key)
Module 1, Init!
第二個(gè)模塊的文件如下:
[lingyun@localhost mod1]$ cd ../mod2/
[lingyun@localhost mod2]$ vim mod_b.c?
?
/********************************************************************************* * Copyright: (C) 2013 fulinux<fulinux@sina.com> * All rights reserved. * * Filename: mod_b.c * Description: This file * * Version: 1.0.0(07/12/2013~) * Author: fulinux <fulinux@sina.com> * ChangeLog: 1, Release initial version on "07/12/2013 10:29:55 AM" * ********************************************************************************/ #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); MODULE_LICENSE("GPL");
?
?
在這里調(diào)用了第一個(gè)模塊中的func1函數(shù)。
對(duì)應(yīng)的Makefile文件:
[lingyun@localhost mod2]$ vim Makefile?
?
obj-m:=mod2.o mod2-y:=mod_b.o KERNELDIR := /lib/modules/$(shell uname -r)/build PWD:=$(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~core .depend .*.cmd *.ko *.ko.* *.mod.c .tmp_versions *odule* $(TARGET)
[lingyun@localhost mod2]$ make
make -C /lib/modules/2.6.32-279.el6.x86_64/build ?M=/usr/local/src/lingyun/fulinux/export_symbol/mod2 modules
make[1]: Entering directory `/usr/src/kernels/2.6.32-279.el6.x86_64'
? Building modules, stage 2.
? MODPOST 1 modules
WARNING: "func1" [/usr/local/src/lingyun/fulinux/export_symbol/mod2/mod2.ko] undefined!
make[1]: Leaving directory `/usr/src/kernels/2.6.32-279.el6.x86_64'
[lingyun@localhost mod2]$?
?
[lingyun@localhost mod2]$ sudo insmod mod2.ko
insmod: error inserting 'mod2.ko': -1 Unknown symbol in module
[lingyun@localhost mod2]$?
解決上面的問題如下:
解決辦法是把mod_a的Module.symvers放到mod_b的當(dāng)前路徑,從而編譯mod_b,符號(hào)信息會(huì)自動(dòng)連接進(jìn)去.
或者在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的值
此時(shí)Makefile文件如下:
?
obj-m:=mod2.o
mod2-y:=mod_b.o
KBUILD_EXTRA_SYMBOLS=~/fulinux/export_symbol/mod1/Module.symvers
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.o *~core .depend .*.cmd *.ko *.ko.* *.mod.c .tmp_versions *odule* $(TARGET)
在編譯加載如下:
?
[lingyun@localhost mod2]$ make
make -C /lib/modules/2.6.32-279.el6.x86_64/build ?M=/usr/local/src/lingyun/fulinux/export_symbol/mod2 modules
make[1]: Entering directory `/usr/src/kernels/2.6.32-279.el6.x86_64'
? CC [M] ?/usr/local/src/lingyun/fulinux/export_symbol/mod2/mod_b.o
? LD [M] ?/usr/local/src/lingyun/fulinux/export_symbol/mod2/mod2.o
? Building modules, stage 2.
? MODPOST 1 modules
? CC ? ? ?/usr/local/src/lingyun/fulinux/export_symbol/mod2/mod2.mod.o
? LD [M] ?/usr/local/src/lingyun/fulinux/export_symbol/mod2/mod2.ko.unsigned
? NO SIGN [M] /usr/local/src/lingyun/fulinux/export_symbol/mod2/mod2.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.32-279.el6.x86_64'
[lingyun@localhost mod2]$ sudo insmod mod2.ko
[lingyun@localhost mod2]$?
[lingyun@localhost mod2]$ dmesg | grep "In Func:"
In Func: func1...
In Func: func2...
可見模塊二調(diào)用模塊一的func1成功!!!
?? ? ?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
