内核中 EXPORT_SYMBOL 标志分析

内核版本:Linux-4.19


1. EXPORT_SYMBOL 的作用:

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

EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);

这两个宏均用于给定的符号导出到模块外部。_GPL版本导出的符号只能被 GPL 许可证下的模块使用。

我们以 EXPORT_SYMBOL 为例。

2. EXPORT_SYMBOL 宏定义如下:

#define EXPORT_SYMBOL(sym)					
	__EXPORT_SYMBOL(sym, "")

3. __EXPORT_SYMBOL 宏定义如下:

#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 */

4. ___EXPORT_SYMBOL 宏定义如下:

/* 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)

5. __KSYMTAB_ENTRY 宏定义如下:

#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;
};

经过层层的宏展开,得到了最终的结果。

6. 分析总结:

在内核符号导出中。调用了EXPORT_SYMBOL(sym),说的来说完成了以下操作:
    (1) 定义一个字符数组存放内核导出符号的名称。并放置到 “__ksymtab_strings” 的 section 中。
    (2) 定义一个内核符号结构用于存放导出符号的内存地址和名称,并放置到 “ "___ksymtab" sec "+" #sym ” 中。
原文地址:https://www.cnblogs.com/GyForever1004/p/10425681.html