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 的迭代无缝地支持序列对象,而且它还允许程 ...
随机推荐
- 自学Aruba4.2-Aruba AC基础配置(1)
点击返回:自学Aruba之路 自学Aruba4.2-Aruba AC基础配置(1) 管理员登陆(admin/saic_admin): Cli Web 管理帐号 控制器基础设置: 控制器恢复出厂设置 查 ...
- mfc editline 变为大框框
属性:
- go语言从零学起(四) -- 基于martini和gorilla实现的websocket聊天实例
如果只是想了解chat的实现方式,在gorilla和revel框架里面都有完整的chat实例可以提供参考.本篇讲解的是,如何基于martini实现websocket的聊天. 配置步骤: 1 已经安装了 ...
- Linux下环境变量设置技巧
Linux下环境变量设置技巧,不用/etc/profile而是在/etc/profile.d目录下新建特定的shell文件来设置 区别: 1.两个文件都是设置环境变量文件的,/etc/profile是 ...
- python---定义一个session类(无错)
import tornado.web #放在内存 redis 文件 数据库 container={} #定义一个session类 class Session: def __init__(self,ha ...
- 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解失效的原因和解决方法
参考原贴地址:https://blog.csdn.net/clementad/article/details/47339519 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Trans ...
- vue 中this指向遇到的坑
vue中的this指向问题 如果方法中没有使用箭头函数,记得把this赋值给另一个变量再使用.
- 10-SQL Server 2008 R2安装步骤
一. 软件和环境 1. 软件 : SQL Server 2008 R2 企业版 软件下载地址:XXXX 2. 环境要求: .Net FrameWork 3.5 以上 (windows 7 ...
- python 小程序,替换文件中的字符串
[root@PythonPC ~]# cat passwd root:x:::root:/root:/bin/bash bin:x:::bin:/bin:/sbin/nologin daemon:x: ...
- python学习笔记9--日志模块logging
我们在写程序的时候经常会打一些日志来帮助我们查找问题,这次学习一下logging模块,在python里面如何操作日志.介绍一下logging模块,logging模块就是python里面用来操作日志的模 ...