linux内核模块(2)导出符号

本文详细解析了Linux内核模块如何导出符号,通过struct kernel_symbol结构体存储符号名称和地址。导出符号的定义包括EXPORT_SYMBOL()宏,以及对应的section在链接脚本中的处理。例如,__kstrtab_my_exp_function位于__ksymtab_strings段,而__ksymtab_my_exp_function位于__ksymtab段。链接脚本如vmlinux.lds.h在模块加载时发挥作用。
摘要由CSDN通过智能技术生成

/*本文由真胖子同志私人定制,烦请转载保留来源http://blog.csdn.net/figtingforlove/article/details/20155485*/

内核模块不但可以使用内核和其他模块导出的符号,还可以向外部导出自己的符号。如果一个模块向外界导出符号,那么模块的编译工具链将负责生成这写导出符号的section(都带有SHF_ALLOC标志),所以在模块的加载过程中会被搬移到CORE section区域。

(1)    导出符号的定义

内核用structkernel_symbol来表示一个内核符号的实例

Linux/include/linux/export.h

19 struct kernel_symbol
 20 {
 21         unsigned long value;    //该符号在内存中的地址
 22         const char *name;       //符号名
 23 };

内核导出符号的宏定义

48 /* For every exported symbol, place a struct in the __ksymtab section */
 49 #define __EXPORT_SYMBOL(sym, sec)                               \
 50         extern typeof(sym) sym;                                 \
 51         __CRC_SYMBOL(sym, sec)                                  \
 52         static const char __kstrtab_##sym[]                     \
 53         __attribute__((section("__ksymtab_strings"), aligned(1))) \
 54         = MODULE_SYMBOL_PREFIX #sym;                            \
 55         static const struct kernel_symbol __ksymtab_##sym       \
 56         __used                                                  \
 57         __attribute__((section("___ksymtab" sec "+" #sym), unused))     \
 58         = { (unsigned long)&sym, __kstrtab_##sym }
 59 
 60 #define EXPORT_SYMBOL(sym)                                      \
 61         __EXPORT_SYMBOL(sym, "")

从源码可以看出,EXPORT_SYMBOL实际上就是定义了两个变量,一个char指针表示符号名,一个stuct kernel_symbol表示一个导出符号。

看一个例子EXPORT_SYMBOL(my_exp_function)

static const char__kstrtab_my_exp_function  = “my_exp_function”;

static const struct kernel_symbol__ksymtab_ my_exp_function = { (unsigned long)& my_exp_function,__kstrtab_ my_exp_function };

实际上内核就是通过一个stuct kernel_symbol对象来向外界表示关于这个符号的两个信息:符号名称和地址。

上面的__kstrtab_my_exp_function会被放在“__ksymtab_strings”段,__ksymtab_ my_exp_function会被放在“__ksymtab”段中,也就是导出符号字符串表段和导出符号表段。而在对这些段的使用需要经过一个中间环节,及链接脚本和链接器部分,下面看一个具体的链接脚本的例子

Linux/include/asm-generic/vmlinux.lds.h

1 #ifndef LOAD_OFFSET

2 #define LOAD_OFFSET 0
3 #endif
4 
5 #ifndef VMLINUX_SYMBOL
6 #define VMLINUX_SYMBOL(_sym_) _sym_
7 #endif
60         /* Kernel symbol table: Normal symbols */                       \
61         __ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {         \
62                 VMLINUX_SYMBOL(__start___ksymtab) = .;                  \
63                 *(__ksymtab)                                  
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值