转自: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模块代码

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/kernel.h>
  4. MODULE_LICENSE("GPL");
  5. int myprint(void)
  6. {
  7. printk("c");
  8. return 0;
  9. }
  10. static int darren_init(void)
  11. {
  12. return 0;
  13. }
  14. static void darren_exit(void)
  15. {
  16. }
  17. module_init(darren_init);
  18. module_exit(darren_exit);
  19. EXPORT_SYMBOL(myprint);

b模块代码

  1. #include <linux/seq_file.h>
  2. #include <linux/cdev.h>
  3. #include <asm/system.h>
  4. MODULE_LICENSE("GPL");
  5. extern int print(void);
  6. static int darren_init(void)
  7. {
  8. int i=0;
  9. printk("b module init\n");
  10. for(;i<10;i++)print();
  11. return 0;
  12. }
  13. static void darren_exit(void)
  14. {
  15. }
  16. module_init(darren_init);
  17. module_exit(darren_exit);

a模块的Makefile如下:

  1. NAME:=a
  2. SYM:=/usr/src/linux-headers-2.6.38-8-generic/Module.symvers
  3. DIR:=/lib/modules/$(shell uname -r)/build/
  4. PWD:=$(shell pwd)
  5. obj-m = $(NAME).o
  6. build:
  7. make -C $(DIR) M=$(PWD)
  8. sudo chmod 777 $(SYM)
  9. sudo sed -i '/myprint/d' $(SYM)
  10. sudo cat Module.symvers>>$(SYM)
  11. sudo chmod 644 $(SYM)

b模块的makefile:

  1. NAME:=b
  2. DIR:=/lib/modules/$(shell uname -r)/build/
  3. PWD:=$(shell pwd)
  4. obj-m = $(NAME).o
  5. build:
  6. 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

内核文档:

  1. Sometimes, an external module uses exported symbols from
  2. another external module. kbuild needs to have full knowledge of
  3. all symbols to avoid spitting out warnings about undefined
  4. symbols. Three solutions exist for this situation.
  5. NOTE: The method with a top-level kbuild file is recommended
  6. but may be impractical in certain situations.
  7. Use a top-level kbuild file
  8. If you have two modules, foo.ko and bar.ko, where
  9. foo.ko needs symbols from bar.ko, you can use a
  10. common top-level kbuild file so both modules are
  11. compiled in the same build. Consider the following
  12. directory layout:
  13. ./foo/ <= contains foo.ko
  14. ./bar/ <= contains bar.ko
  15. The top-level kbuild file would then look like:
  16. #./Kbuild (or ./Makefile):
  17. obj-y := foo/ bar/
  18. And executing
  19. $ make -C $KDIR M=$PWD
  20. will then do the expected and compile both modules with
  21. full knowledge of symbols from either module.
  22. Use an extra Module.symvers file
  23. When an external module is built, a Module.symvers file
  24. is generated containing all exported symbols which are
  25. not defined in the kernel. To get access to symbols
  26. from bar.ko, copy the Module.symvers file from the
  27. compilation of bar.ko to the directory where foo.ko is
  28. built. During the module build, kbuild will read the
  29. Module.symvers file in the directory of the external
  30. module, and when the build is finished, a new
  31. Module.symvers file is created containing the sum of
  32. all symbols defined and not part of the kernel.
  33. Use "make" variable KBUILD_EXTRA_SYMBOLS
  34. If it is impractical to copy Module.symvers from
  35. another module, you can assign a space separated list
  36. of files to KBUILD_EXTRA_SYMBOLS in your build file.
  37. These files will be loaded by modpost during the
  38. initialization of its symbol tables.

driver: linux2.6 内核模块导出函数实例(EXPORT_SYMBOL) 【转】的更多相关文章

  1. linux模块导出符号 EXPORT_SYMBOL_GPL&EXPORT_SYMBOL(转)

    转自:http://blog.csdn.net/angle_birds/article/details/7396748 一个模块mod1中定义一个函数func1:在另外一个模块mod2中定义一个函数f ...

  2. AFX_MANAGE_STATE(AfxGetStaticModuleState())DLL导出函数包含MFC资源

    AFX_MANAGE_STATE(AfxGetStaticModuleState()) 先看一个例子: .创建一个动态链接到MFC DLL的规则DLL,其内部包含一个对话框资源.指定该对话框ID如下: ...

  3. DLL 导出函数

    DLL的链接方式分为两种:隐式链接和显式链接 DLL导出的函数 和 导出类在调用时,有些区别,这里暂时不讲,直说简单的导出函数: 隐式链接: #include "stdafx.h" ...

  4. dll导出函数的两种方式的比较

    最初的网页链接已经挂了, 在此贴一个中间的转载链接 https://blog.csdn.net/zhazhiqiang/article/details/51577523 一 概要 vs中导出 dll的 ...

  5. DLL导出函数和类的定义区别 __declspec(dllexport)

    DLL导出函数和类的定义区别 __declspec(dllexport) 是有区别的, 请看 : //定义头文件的使用方,是导出还是导入 #if defined(_DLL_API) #ifndef D ...

  6. 分享一个批量导出当前实例下的所有linkedserver脚本

    分享一个批量导出当前实例下的所有linkedserver脚本 很多时候,我们都需要导出实例下面的登录用户,job,linkedserver等等 导出job比较复杂,下午写了一个脚本把所有的linked ...

  7. JavaScript学习笔记-函数实例

    函数实例 var p = { a:15, b:'5', f1:function(){ var self = this; console.log(self.a+self.b); f2(); functi ...

  8. Mysql导出函数、存储过程

    下面是导出存储过程的代码 1 # mysqldump -u 数据库用户名 -p -n -t -d -R 数据库名 > 文件名 其中,-d 表示--no-create-db, -n表示--no-d ...

  9. python迭代器与iter()函数实例教程

    python迭代器与iter()函数实例教程 发布时间:2014-07-16编辑:脚本学堂 本文介绍了python迭代器与iter()函数的用法,Python 的迭代无缝地支持序列对象,而且它还允许程 ...

随机推荐

  1. 牛客练习赛 小A与最大子段和 解题报告

    小A与最大子段和 题意 在一个序列 \(\{a\}\) 里找到一个非空子段 \(\{b\}\), 满足 \(\sum\limits_{i=1}^{|b|}b_i\times i\) 最大 \(n\le ...

  2. 解决Ubuntu17.04以上系统,yarn init报错

    安装yarn的时候老是装了个cmdtes的东西,官网是说删掉cmdtest重装就行,但是真没用. 正确的解决办法应该是像这位说的一样,先修改一下源,sudo apt update再下载,就能下载到真正 ...

  3. Spring Cloud(三) --- hystrix

    Hystrix 说到Hystrix就得先说一下产生的背景等等,那就是雪崩效应. 在微服务中肯定存在多个服务层之间的调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服 ...

  4. 【UR #17】滑稽树前做游戏

    假装看懂的样子 假装会做的样子 UOJ Round #17 题解 加上一个(t-w)^c,c是和i相连的点的度数 是一个多项式的话可以归纳证明 一些具体实现: 多项式存储,保留t,y, f=ai*t^ ...

  5. SQL Server 增、删、改、小部分查

    --现有三个表Student.Score.Course.Teacher create table Student ( Sno ) not null,--学号 Sname ) not null,--姓名 ...

  6. ??? cliquers

    解:先推一个式子,然后就是CRT了... 那个阶乘怎么求呢?主要是分母可能有0,这时我们把分母的因子p全部提出来,上下次数相减判断即可. 细节颇多......注意在快速幂开始的时候a %= MO是个好 ...

  7. 常用linux命令(项目部署)

    centos 图形 命令行 界面切换 如果在图形界面下,按:Ctrl+Alt+F2进入如下命令行界面 -------------- 看当前目录的路径: pwd ................... ...

  8. linux centos7安装python3

    折腾 Python官网: https://www.python.org/ 查看相关评论,众人大呼python2与python3为两种语言,既然继承性不大,那我也就直接学python3了. 在系统选择, ...

  9. Python基础【day03】:文件操作(七)

    零.本节内容 1.文件常用操作汇总 2.打开文件 3.操作文件 4.关闭文件 一.文件常用操作汇总 二.打开文件 1.普通打开模式 r,英文:read,只读模式(默认) w,英文:write,只写模式 ...

  10. Python基础【day03】:字符转编码操作(五)

    本节内容 1.编码介绍 2.字符编码介绍 3.总结 说到python的编码,一句话总结,说多了都是泪啊,这个在以后的python的开发中绝对是一件令人头疼的事情.所以有必要要讲讲清楚 一.编码介绍 1 ...