Linux 驱动开发之内核模块开发(四)—— 符号表的导出

 Linux内核头文件提供了一个方便的方法用来管理符号的对模块外部的可见性,因此减少了命名空间的污染(命名空间的名称可能会与内核其他地方定义的名称冲突),并且适当信息隐藏。 如果你的模块需要输出符号给其他模块使用,应当使用下面的宏定义:

EXPORT_SYMBOL(name);

EXPORT_SYMBOL_GPL(name);   //只适用于包含GPL许可权的模块;

     这两个宏均用于将给定的符号导出到模块外. _GPL版本的宏定义只能使符号对GPL许可的模块可用。 符号必须在模块文件的全局部分导出,不能在函数中导出,这是因为上述这两个宏将被扩展成一个特殊用途的声明,而该变量必须是全局的。这个变量存储于模块的一个特殊的可执行部分(一个"ELF段" ),在装载时,内核通过这个段来寻找模块导出的变量(感兴趣的读者可以看<linux/module.h>获知更详细的信息)。


一、宏定义EXPORT_SYMBOL分析

1、源码

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. <include/linux/moudule.h>  
  2.   
  3. …….  
  4.   
  5. #ifndef MODULE_SYMBOL_PREFIX  
  6. #define MODULE_SYMBOL_PREFIX ""  
  7. #endif  
  8.   
  9. …….  
  10.   
  11. struct kernel_symbol       //内核符号结构  
  12. {  
  13.        unsignedlong value;  //该符号在内存地址中的地址  
  14.        constchar *name;     //该符号的名称  
  15.   
  16. };  
  17.   
  18. ……  
  19.   
  20. #define __EXPORT_SYMBOL(sym,sec)                                 \  
  21.        externtypeof(sym) sym;                                                        \  
  22.        __CRC_SYMBOL(sym,sec)                                            \  
  23.        staticconst char __kstrtab_##sym[]                                 \  
  24.        __attribute__((section(“__ksymtab_strings”),aligned(1)))   \  
  25.        =MODULE_SYMBOL_PREFIX#sym;                      \  
  26.        staticconst struct kernel_symbol __ksymtab_##sym         \  
  27.        __used                                                                          \  
  28.        __attribute__((section(“__ksymatab”sec),unused))                   \  
  29.        ={(unsignedlong)&sym,_kstrab_#sym}   
  30.   
  31. #define    EXPORT_SYMBOL(sym)                   \  
  32.               __EXPOTR_SYMBOL(sym,””)  
  33.   
  34. #define    EXPORT_SYMBOL_GPL(sym)           \  
  35.               __EXPOTR_SYMBOL(sym,”_gpl”)  
  36.   
  37. #define    EXPORT_SYMBOL(sym)                   \  
  38.               __EXPOTR_SYMBOL(sym,”_gpl_future”)  

在分析前,先了解如下相关知识:

1)#运算符,##运算符

     通常在宏定义中使用#来创建字符串 #abc就表示字符串”abc”等。

    ##运算符称为预处理器的粘合剂,用来替换粘合两个不同的符号,

如:#define xName (n)  x##n

则xName(4)  则变为x4


2)gcc的 __attribute__ 属性:

     __attribute__((section(“section_name”)))的作用是将指定的函数或变量放入到名为”section_name”的段中

    __attribute__属性添加可以在函数或变量定义的时候直接加入在定义语句中。

如:

int myvar__attribute__((section("mydata"))) = 0;

表示定义了整形变量myvar=0;并且将该变量存放到名为”mydata”的section中

关于gcc_attribute详解可以参考:http://blog.sina.com.cn/s/blog_661314940100qujt.html


2、EXPORT_SYMBOL的作用是什么?

       EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。

       这里要和System.map做一下对比:System.map 中的是连接时的函数地址。连接完成以后,在2.6内核运行过程中,是不知道哪个符号在哪个地址的。

       EXPORT_SYMBOL的符号,是把这些符号和对应的地址保存起来,在内核运行的过程中,可以找到这些符号对应的地址。而模块在加载过程中,其本质就是能动态连接到内核,如果在模块中引用了内核或其它模块的符号,就要EXPORT_SYMBOL这些符号,这样才能找到对应的地址连接。


二、 EXPORT_SYMBOL使用方法

第一、在模块函数定义之后使用EXPORT_SYMBOL(函数名)

第二、在调用该函数的模块中使用extern对之声明

第三、首先加载定义该函数的模块,再加载调用该函数的模块

要调用别的模块实现的函数接口和全局变量,就要导出符号 /usr/src/linux-headers-2.6.32-33-generic/Module.symvers

A B
static int num =10;
static void show(void)
{
printk("%d  \n",num);
}
EXPORT_SYMBOL(show);
extern void show(void);


函数A先将show() 函数导出,函数B 使用extern 对其声明,要注意:

a -- 编译a模块后,要将 Module.symvers 拷贝到b模块下

b -- 然后才能编译b模块

c -- 加载:先加载a模块,再加载b模块

d -- 卸载:先卸载b模块,再卸载a模块


三、示例

代码a ,hello.c
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. #include <linux/module.h>  
  2.   
  3. static int num =10;  
  4. static void show(void)  
  5. {  
  6.     printk("show(),num = %d\n",num);  
  7. }  
  8. static int hello_init(void)  
  9. {  
  10.     printk("hello_init");  
  11.     return 0;  
  12. }  
  13. static void hello_exit(void)  
  14. {  
  15.     printk("hello_exit \n");  
  16. }  
  17. EXPORT_SYMBOL(show);  
  18. MODULE_LICENSE("GPL");  
  19. module_init(hello_init);  
  20. module_exit(hello_exit);  

代码b show.c
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. #include <linux/module.h>  
  2.   
  3. extern void show(void);  
  4.   
  5. static int show_init(void)  
  6. {  
  7.     printk("show_init");  
  8.     show();  
  9.     return 0;  
  10. }  
  11. static void show_exit(void)  
  12. {  
  13.     printk("show_exit \n");  
  14. }  
  15.   
  16. MODULE_LICENSE("GPL");  
  17.   
  18. module_init(show_init);  
  19. module_exit(show_exit);<strong>  
  20. </strong>  

编译后加载模块,卸载模块,可以用 dmesg 查看内核打印信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/402117.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 驱动开发之内核模块开发 (三)—— 模块传参

一、module_param() 定义 通常在用户态下编程&#xff0c;即应用程序&#xff0c;可以通过main()的来传递命令行参数&#xff0c;而编写一个内核模块&#xff0c;则通过module_param() 来传参。 module_param()宏是Linux 2.6内核中新增的&#xff0c;该宏被定义在include/linux…

Exynos4412 文件系统制作(二)—— 文件系统简介

一、Linux磁盘分区和目录 Linux发行版本之间的差别很少&#xff0c;差别主要表现在系统管理的特色工具以及软件包管理方式的不同。目录结构基本上都是一样的。 Windows的文件结构是多个并列的树状结构&#xff0c;最顶部的是不同的磁盘&#xff08;分区&#xff09;&#xff0c…

MM引擎新应用——爱车加油记

基于MM应用引擎开发的EXTJS应用&#xff0c;车主每次加完汽油后&#xff0c;记录加油时的里程数以及加油金额和汽油价格&#xff0c;就可计算出上次加油后行驶的里程数、上次加油的平均油耗。点击刷新按钮&#xff0c;即可计算有记录以来的行驶公里数和再次期间加油金额和平均油…

### 阅读之痕-2013/11

2019独角兽企业重金招聘Python工程师标准>>> 阅读之痕-2013/11 Andy erpingwugmail.com 2013/11/01-2013/11/30 2013/11/01-2013/11/30 The story of rocksdb - Embedded key-value store for Flash and RAM http://rocksdb.org/intro.pdf High Performance Network…

Exynos4412 内核移植(六)—— 设备树解析

一、描述ARM Device Tree起源于OpenFirmware (OF)&#xff0c;在过去的Linux中&#xff0c;arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码&#xff0c;相当多数的代码只是在描述板级细节&#xff0c;而这些板级细节对于内核来讲&#xff0c;不过是垃圾&#xff…

Github Page创建个人主页以及绑定域名

2019独角兽企业重金招聘Python工程师标准>>> 在github中 我们可以通过github page创建个人主页 以及绑定域名 据说有300m空间 以及无限流量 不过只能支持静态html 以及一些脚本语言 顺便吐槽一下 阿里云最低配那个云空间服务器 512m内存 启动web服务器后 mys…

Exynos4412 内核移植(五)—— 驱动的移植

以移植自己制作的驱动&#xff0c;学习内核移植中的驱动移植&#xff0c;及 驱动程序的动态编译和静态编译 硬件环境&#xff1a; Linux 内核版本&#xff1a;Linux 3.14 主机&#xff1a;Ubuntu 12.04发行版 目标机&#xff1a;FS4412平台 交叉编译工具&#xff1a;arm-none-l…

FTP文件共传输服务

FTP文件共传输服务一&#xff0c;vsftpd服务基础&#xff08;1&#xff09;&#xff0c;FTP服务概述FTP&#xff08;File Transfer Protocol&#xff0c;文件传输协议&#xff09;是典型的C/S结构的应用层协议&#xff0c;需要由服务端软件、客户端软件共同实现文件传达输功能…

Exynos4412 内核移植(四)—— MMU 相关知识解析

一、MMU的产生 许多年以前&#xff0c;当人们还在使用DOS或是更古老的操作系统的时候&#xff0c;计算机的内存还非常小&#xff0c;一般都是以K为单位进行计算&#xff0c;相应的&#xff0c;当时的程序规模也不大&#xff0c;所以内存容量虽然小&#xff0c;但还是可以容纳当…

Mysql limit 子查询

为什么80%的码农都做不了架构师&#xff1f;>>> &#xff08;1&#xff09;mysql limit 不支持子查询像下面这条语句无法执行 SELECT * FROM b_c_s1 where CT_ID IN (SELECT DISTINCT CT_ID FROM b_c_s1 LIMIT 0,2); &#xff08;2&#xff09;应该在只查询外面再…

Exynos4412 内核移植(二)—— 内核编译过程分析

内核的编译同样是从Makefile 来分析&#xff1a; 一、内核源码结构 Linux内核文件数目近2万&#xff0c;出去其他架构CPU的相关文件&#xff0c;他们分别位于顶层目录下的17个子目录&#xff0c;各个目录功能独立&#xff0c;下面是常用目录&#xff1a; arch:体系结构相关代码…

深入理解Java:注解(Annotation)

2019独角兽企业重金招聘Python工程师标准>>> 一、概述 1.什么是注解&#xff08;Annotation&#xff09; Annotation&#xff08;注解&#xff09;就是Java提供了一种元程序中的元素关联任何信息和着任何元数据&#xff08;metadata&#xff09;的途径和方法。Ann…

Exynos4412 内核移植(三)—— 内核启动过程分析

内核启动所用函数如下&#xff1a; 与移植U-Boot 的过程相似&#xff0c;在移植Linux 之前&#xff0c;先了解它的启动过程。Linux 的过程可以分为两部分&#xff1a;架构/开发板相关的引导过程、后续的通用启动过程。对于uImage、zImage ,它们首先进行自解压得到vmlinux &…

开源自己用python封装的一个Windows GUI(UI Automation)自动化工具,支持MFC,Windows Forms,WPF,Metro,Qt...

首先&#xff0c;大家可以看下这个链接 Windows GUI自动化测试技术的比较和展望 。 这篇文章介绍了Windows中GUI自动化的三种技术&#xff1a;Windows API, MSAA - Microsoft Active Accessibility, UIAutomation 用脚本语言AutoIT实现自动化就是第一种技术Windows API, 查找窗…

Exynos4412 Uboot 移植(六)—— 相关知识补充

Uboot版本&#xff1a;u-boot-2013.01 一、gd结构体的定义与使用 gd_t 和 bd_t 是u-boot中两个重要的数据结构&#xff0c;在初始化操作很多都要靠这两个数据结构来保存或传递。 gd_t 定义在/u-boot-2013.01/arch/arm/include/asm/global_data.h bd_t 定义在 ./include/asm-ar…

Exynos4412 Uboot 移植(五)—— Uboot 移植过程

Uboot 版本&#xff1a;u-boot-2013.01 开发板&#xff1a;FS_4412 平台&#xff08;Exynos4412,可以根据自己的板子修改&#xff0c;只要是4412的过程都是一样的&#xff09; 一、建立自己的平台 1、下载源码 我们可以在下面这个网站上下载最新的和以前任一版本的uboot ftp://…

Nagios 安装及常见错误

一、实验环境监控服务器&#xff08;nagios服务器--192.168.1.100&#xff09;CentOS5.4 nagios-3.2.1 nagios-plugins-1.4.14 nrpe-2.12被监控客户端&#xff08;linux客户端--192.168.1.200&#xff09;CentOS5.4 nagios-plugins-1.4.14 nrpe-2.12二、nrpe插件1、nrpe插…

Exynos4412 Uboot 移植(四)—— Uboot引导内核过程分析

bootloader 要想启动内核&#xff0c;可以直接跳到内核的第一个指令处&#xff0c;即内核的起始地址&#xff0c;这样便可以完成内核的启动工作了。但是要想启动内核还需要满足一些条件&#xff0c;如下所示&#xff1a; 1、cpu 寄存器设置 * R0 0 * R1 机器类型 id …

Exynos4412 Uboot 移植(三)—— Uboot添加自定义命令

Uboot添加自定义命令&#xff1a;uboot中的命令使用U_BOOT_CMD这个宏声明来注册进系统&#xff0c;链接脚本会把所有的cmd_tbl_t结构体放在相邻的地方。 UBoot版本&#xff1a;u-boot-2013.01 一、U-Boot命令的格式 即使是内核的启动&#xff0c;也是通过U-Boot命令来实现的。…