driver: linux2.6 内核模块导出函数实例(EXPORT_SYMBOL) 【转】
2015-06-04 14:07
561 查看
转自: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.
内核版本: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.
相关文章推荐
- 使用 ftrace 调试 Linux 内核 (二)
- 从Linux内核中获取真随机数【转】
- 使用 ftrace 调试 Linux 内核 (一)
- Linux学习笔记(06-04)创建进程
- Linux Tools Quick Tutorial
- linux fork函数浅析
- linux下批量执行mysql指令实例
- linux 断电后出现问题
- Linux释放cached的方法
- Linux下加载iso光盘镜像的方法
- linux定时器
- linux grep命令
- Ubuntu如何从user用户切换到root用户
- centos rm回收站
- Windows Socket和Linux Socket编程的区别
- 实战-----使用crond 在linux中定时执行任务
- [DB2]linux下安装db2 v9.7
- Linux 内核内存泄露工具使用
- linux 软链接
- ODROID-X2 SD card install Arch linux