EXPORT_SYMBOL 定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在其它内核模块中直接调用,即使用 EXPORT_SYMBOL 可以将一个函数以符号的方式导出给其他模块使用。
EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);
这两个宏均用于给定的符号导出到模块外部。_GPL版本导出的符号只能被 GPL 许可证下的模块使用。
我们以 EXPORT_SYMBOL 为例。
#define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "")
#include <generated/autoksyms.h>
#define __EXPORT_SYMBOL(sym, sec) __cond_export_sym(sym, sec, __is_defined(__KSYM_##sym))
#define __cond_export_sym(sym, sec, conf) ___cond_export_sym(sym, sec, conf)
#define ___cond_export_sym(sym, sec, enabled) __cond_export_sym_##enabled(sym, sec)
#define __cond_export_sym_1(sym, sec) ___EXPORT_SYMBOL(sym, sec)
#define __cond_export_sym_0(sym, sec) /* nothing */
/* For every exported symbol, place a struct in the __ksymtab section */
#define ___EXPORT_SYMBOL(sym, sec) extern typeof(sym) sym; __CRC_SYMBOL(sym, sec) static const char __kstrtab_##sym[] __attribute__((section("__ksymtab_strings"), used, aligned(1))) = #sym; __KSYMTAB_ENTRY(sym, sec)
#define __KSYMTAB_ENTRY(sym, sec) static const struct kernel_symbol __ksymtab_##sym __attribute__((section("___ksymtab" sec "+" #sym), used)) = { (unsigned long)&sym, __kstrtab_##sym }
struct kernel_symbol {
unsigned long value;
const char *name;
};
经过层层的宏展开,得到了最终的结果。
在内核符号导出中。调用了EXPORT_SYMBOL(sym),说的来说完成了以下操作:
(1) 定义一个字符数组存放内核导出符号的名称。并放置到 “__ksymtab_strings” 的 section 中。
(2) 定义一个内核符号结构用于存放导出符号的内存地址和名称,并放置到 “ "___ksymtab" sec "+" #sym ” 中。
原文:https://www.cnblogs.com/GyForever1004/p/10425681.html