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

  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.     
  8.     make -C (DIR)M=(DIR)M=(PWD)
  9.     sudo chmod 777 $(SYM)
  10.     sudo sed -i '/myprint/d' $(SYM)
  11.     sudo cat Module.symvers>>$(SYM)
  12.     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=(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.             makeCmake−CKDIR 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.













本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/4551671.html,如需转载请自行联系原作者


相关文章
|
7月前
|
安全 网络协议 Linux
深入理解Linux内核模块:加载机制、参数传递与实战开发
本文深入解析了Linux内核模块的加载机制、参数传递方式及实战开发技巧。内容涵盖模块基础概念、加载与卸载流程、生命周期管理、参数配置方法,并通过“Hello World”模块和字符设备驱动实例,带领读者逐步掌握模块开发技能。同时,介绍了调试手段、常见问题排查、开发规范及高级特性,如内核线程、模块间通信与性能优化策略。适合希望深入理解Linux内核机制、提升系统编程能力的技术人员阅读与实践。
706 1
|
7月前
|
Ubuntu Linux
Ubuntu 23.04 用上 Linux 6.2 内核,预计下放到 22.04 LTS 版本
Linux 6.2 带来了多项内容更新,修复了 AMD 锐龙处理器设备在启用 fTPM 后的运行卡顿问题,还增强了文件系统。
|
7月前
|
Ubuntu Linux
Ubuntu 23.10 现在由Linux内核6.3提供支持
如果你想在你的个人电脑上测试一下Ubuntu 23.10的最新开发快照,你可以从官方下载服务器下载最新的每日构建ISO。然而,请记住,这是一个预发布版本,所以不要在生产机器上使用或安装它。
|
7月前
|
传感器 监控 Ubuntu
10 月发布,Ubuntu 23.10 已升级到 Linux Kernel 6.3 内核
硬件方面,Linux 6.3 引入了在 HID 中引入了原生的 Steam Deck 控制器接口,允许罗技 G923 Xbox 版赛车方向盘在 Linux 上运行;改善 8BitDo Pro 2 有线控制器的行为;并为一系列华硕 Ryzen 主板添加传感器监控。
|
7月前
|
Ubuntu Linux
Ubuntu24.04LTS默认采用Linux 6.8内核,实验性版本可通过PPA获得
IT之家提醒,当下的 Ubuntu 23.10 也是一个“短期支持版本”,该版本将在今年 7 月终止支持,而今年 4 月推出的 Ubuntu 24.04 LTS 长期支持版本将获得 5 年的更新支持。
|
7月前
|
监控 Ubuntu Linux
什么Linux,Linux内核及Linux操作系统
上面只是简单的介绍了一下Linux操作系统的几个核心组件,其实Linux的整体架构要复杂的多。单纯从Linux内核的角度,它要管理CPU、内存、网卡、硬盘和输入输出等设备,因此内核本身分为进程调度,内存管理,虚拟文件系统,网络接口等4个核心子系统。
618 0
|
7月前
|
Web App开发 缓存 Rust
|
7月前
|
Ubuntu 安全 Linux
Ubuntu 发行版更新 Linux 内核,修复 17 个安全漏洞
本地攻击者可以利用上述漏洞,攻击 Ubuntu 22.10、Ubuntu 22.04、Ubuntu 20.04 LTS 发行版,导致拒绝服务(系统崩溃)或执行任意代码。
|
7月前
|
Ubuntu 机器人 物联网
Linux Ubuntu 22.04 LTS 测试版实时内核已可申请
请注意,在启用实时内核后您需要手动配置 grub 以恢复到原始内核。更多内容请参考: