Linux源码 EXPORT_SYMBOL
阅读数:239 评论数:0
跳转到新版页面分类
Linux
正文
一、概述
在Linux内核中,EXPORT_SYMBOL
宏允许内核模块导出符号(通常是函数或变量),使得其他模块可以在它们自己的代码中使用这些符号。这是一种模块间通信的机制,允许模块共享代码而不需要将代码复制到每个模块中。
例如,如果一个内核模块实现了一个特定的功能,它可以通过EXPORT_SYMBOL
导出一个函数,然后其他模块就可以调用这个函数,而不需要知道其具体实现。这样可以减少代码冗余,并允许模块之间解耦合。
下面是一个简单的示例,说明了如何使用EXPORT_SYMBOL
:
#include <linux/module.h>
// 一个简单的函数,我们希望其他模块能够使用
int my_shared_function(int arg) {
printk(KERN_INFO "my_shared_function was called with arg = %d\n", arg);
return arg + 1;
}
// 使用EXPORT_SYMBOL宏导出my_shared_function
EXPORT_SYMBOL(my_shared_function);
// 模块初始化函数
static int __init my_module_init(void) {
printk(KERN_INFO "My module loaded\n");
return 0;
}
// 模块卸载函数
static void __exit my_module_exit(void) {
printk(KERN_INFO "My module unloaded\n");
}
module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple example module with exported symbol");
在这个例子中,函数my_shared_function
被导出,其他加载到内核的模块就可以声明并使用这个函数。需要注意的是,使用EXPORT_SYMBOL
导出的符号可以被任何模块使用,不论模块的许可证是什么。如果你想要限制只有GPL兼容的模块才能使用这个符号,那么应该使用EXPORT_SYMBOL_GPL
宏。
要使用导出的符号,其他模块需要在它们的代码中声明它们想要使用的外部符号。例如:
extern int my_shared_function(int arg);
然后,这个模块就可以调用my_shared_function
,就像它是本地定义的一样。
二、源码相关
查看linux/export.h文件:
struct kernel_symbol //内核符号结构
{
unsigned long value; //该符号在内存地址中的地址
const char *name; //该符号的名称
};
预备知识:
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中。
示例分析:如调用EXPORT_SYMBOL(myfc)
展开为__EXPORT_SYMBOL(myfc," ")
继续展开为:
static const char __kstrtab_myfc[]
__attribute__((section("__ksymtab_strings"), aligned(1))) \
= VMLINUX_SYMBOL_STR(myfc);
static const struct kernel_symbol __ksymtab_myfc \
__used \
__attribute__((section("___ksymtab" sec "+" #sym), used)) \
= { (unsigned long)&sym, __kstrtab_myfc }
定义了一个字符数组__kstrtab_myfc[]用于存放导出的符号名myfc。
定义了一个内核符号结构__ksymtab_myfc用于存放引出符号myfc在内存中的地址和名称
总结: 在内核符号导出中,调用了EXPORT_SYMBOL(sym), 则会完成以下操作:
(1) 定义一个字符数组存放内核符号的名称,并放置到"__ksymtab_strings"的section中.
(2)定义一个内核符号结构用于存放导出符号的内存地址和名称,并放置到"__ksymatab"中.
即通过EXPORT_SYMBOL(sym)先放了内核以外的世界关于这个符号两点信息: 内核符号的名称和其内存地址.