driver: linux2.6 内核模块导出函数实例(EXPORT_SYMBOL) 【转】
转自: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) 【转】的更多相关文章
- linux模块导出符号 EXPORT_SYMBOL_GPL&EXPORT_SYMBOL(转)
转自:http://blog.csdn.net/angle_birds/article/details/7396748 一个模块mod1中定义一个函数func1:在另外一个模块mod2中定义一个函数f ...
- AFX_MANAGE_STATE(AfxGetStaticModuleState())DLL导出函数包含MFC资源
AFX_MANAGE_STATE(AfxGetStaticModuleState()) 先看一个例子: .创建一个动态链接到MFC DLL的规则DLL,其内部包含一个对话框资源.指定该对话框ID如下: ...
- DLL 导出函数
DLL的链接方式分为两种:隐式链接和显式链接 DLL导出的函数 和 导出类在调用时,有些区别,这里暂时不讲,直说简单的导出函数: 隐式链接: #include "stdafx.h" ...
- dll导出函数的两种方式的比较
最初的网页链接已经挂了, 在此贴一个中间的转载链接 https://blog.csdn.net/zhazhiqiang/article/details/51577523 一 概要 vs中导出 dll的 ...
- DLL导出函数和类的定义区别 __declspec(dllexport)
DLL导出函数和类的定义区别 __declspec(dllexport) 是有区别的, 请看 : //定义头文件的使用方,是导出还是导入 #if defined(_DLL_API) #ifndef D ...
- 分享一个批量导出当前实例下的所有linkedserver脚本
分享一个批量导出当前实例下的所有linkedserver脚本 很多时候,我们都需要导出实例下面的登录用户,job,linkedserver等等 导出job比较复杂,下午写了一个脚本把所有的linked ...
- JavaScript学习笔记-函数实例
函数实例 var p = { a:15, b:'5', f1:function(){ var self = this; console.log(self.a+self.b); f2(); functi ...
- Mysql导出函数、存储过程
下面是导出存储过程的代码 1 # mysqldump -u 数据库用户名 -p -n -t -d -R 数据库名 > 文件名 其中,-d 表示--no-create-db, -n表示--no-d ...
- python迭代器与iter()函数实例教程
python迭代器与iter()函数实例教程 发布时间:2014-07-16编辑:脚本学堂 本文介绍了python迭代器与iter()函数的用法,Python 的迭代无缝地支持序列对象,而且它还允许程 ...
随机推荐
- 06 Zabbix分布式监控和主被动模式
06 Zabbix分布式监控和主被动模式 zabbix proxy设置 使用zabbix代理的好处 监控拥有不可靠的远程区域 当监控项目数以万计的时候使用代理分担zabbix-proxy压力 简化分布 ...
- 【BZOJ2142】礼物(拓展卢卡斯定理)
[BZOJ2142]礼物(拓展卢卡斯定理) 题面 BZOJ 洛谷 题解 显然如果\(\sum w_i>n\)无解. 否则答案就是:\(\displaystyle \prod_{i=1}^m{n- ...
- UOJ #164. 【清华集训2015】V | 线段树
题目链接 UOJ #164 题解 首先,这道题有三种询问:区间加.区间减(减完对\(0\)取\(\max\)).区间修改. 可以用一种标记来表示--标记\((a, b)\)表示把原来的值加上\(a\) ...
- 【转】STC51单片机下载程序的时候不要在VCC端接DHT11
今天使用51单片机学习板调试DHT11湿度传感器,下载程序的时候把DHT11烧掉了. 一开始我使用杜邦线把DHT11的VCC引脚接到学习板上的VCC端,GND接GND,数据端口接51单片机的P0.0. ...
- 【洛谷P1273】有线电视网
题目大意:给定一棵 N 个节点的有根树,1 号节点为根节点,叶子节点有点权,每条边有边权,每经过一条边都减去该边权,每经过一个节点都加上该点权,求在保证权值和为非负数的前提下最多能经过多少个叶子节点. ...
- 关于vue-devtools安装
两种方法. 第一种:使用https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbp ...
- java基础基础总结----- 常用了解java(二)
一.Java的发展历史 1998年,Java 2 Platform J2SE.J2ME.J2EE 2005年,Java10周年,重新命名: J2SE → Java SE → Standard Edit ...
- mysql盲注学习-1
mysql: 1.left() //left()函数 left(a,b)从左侧截取a,的b位 2.mid() //mid()函数 参数 描述 column_name 必需.要提取字符的字段. star ...
- ELK 5.6.8 安装部署
操作系统版本: LSB Version: :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64: ...
- .Net MVC 当前上下文中不存在名称“Style”
遇到了这种问题,最后居然是我拼写错误了... 当然也有其他原因 http://blog.csdn.net/bianchao1/article/details/69666347 按照上面这篇博客的方法先 ...