EXPORT_SYMBOL 底层原理

文章目录

前言

EXPORT_SYMBOL 是 Linux 内核中用于导出符号(函数或变量)供其他模块使用的宏。理解其底层原理需要了解内核模块加载过程和内核符号表管理。

EXPORT_SYMBOL 工作原理

1、宏定义和预处理

EXPORT_SYMBOL 宏定义在内核头文件中(通常在 include/linux/export.h 中)。它将符号添加到一个特定的段(section)中。

c 复制代码
#define EXPORT_SYMBOL(sym)          \
    __EXPORT_SYMBOL(sym, "")

__EXPORT_SYMBOL 又定义为:

c 复制代码
#define __EXPORT_SYMBOL(sym, sec)                    \
    extern typeof(sym) sym;                          \
    static const char __kstrtab_##sym[]              \
    __attribute__((section("__ksymtab_strings"), aligned(1))) \
    = #sym;                                          \
    static const struct kernel_symbol __ksym_##sym   \
    __attribute__((section("__ksymtab" sec), used))  \
    = { (unsigned long)&sym, __kstrtab_##sym }

2、内核符号表

EXPORT_SYMBOL 将符号和符号名字符串分别放在 __ksymtab 和 __ksymtab_strings 段中。__ksymtab 是内核符号表,包含所有导出的符号。

3、链接时处理

编译模块时,这些段会被链接器识别并保存在相应的模块对象文件中。内核在加载模块时会将这些符号表信息提取并合并到全局符号表中。

4、模块加载

当加载一个模块时,内核会处理模块的符号表段并注册所有的导出符号。内核符号表包含全局可见的符号,可以通过查找符号名找到其地址。

详细的过程

1、定义和编译

假设你有一个模块定义了一个符号并导出它:

c 复制代码
// mymodule.c
int my_function(int x) {
    return x * 2;
}
EXPORT_SYMBOL(my_function);

这段代码会生成类似以下内容的符号表项:

c 复制代码
static const char __kstrtab_my_function[] __attribute__((section("__ksymtab_strings"), aligned(1))) = "my_function";
static const struct kernel_symbol __ksym_my_function __attribute__((section("__ksymtab"), used)) = { (unsigned long)&my_function, __kstrtab_my_function };

2、链接阶段

编译器会将这些信息放在模块的 .o 文件的 __ksymtab 和 __ksymtab_strings 段中。

3、加载模块:

当内核加载这个模块时,它会处理 __ksymtab 和 __ksymtab_strings 段,将符号注册到全局符号表中。加载过程中的关键函数是 simplify_symbols() 和 simplify_reloc(),它们会解析和处理这些符号。

4、符号查找:

内核中的其他模块可以通过 extern 关键字引用这些符号。当引用这些符号的模块加载时,内核会在全局符号表中查找这些符号,并解析符号地址。

示例

假设你有两个模块,分别是 mymodule.c 和 othermodule.c:

c 复制代码
// mymodule.c
int my_function(int x) {
    return x * 2;
}
EXPORT_SYMBOL(my_function);
c 复制代码
// othermodule.c
extern int my_function(int x);

void call_my_function(void) {
    int result = my_function(10);
    printk(KERN_INFO "Result: %d\n", result);
}

编译和加载 mymodule 后,再加载 othermodule。othermodule 加载时,内核会解析 my_function 的符号地址,并正确调用 mymodule 中的 my_function 函数。

总结

EXPORT_SYMBOL 的底层原理是通过将符号和符号名存储在特定段中,内核在模块加载时处理这些段并将符号注册到全局符号表,从而实现符号的共享和复用。

相关推荐
再睡一夏就好几秒前
Linux常见工具如yum、vim、gcc、gdb的基本使用,以及编译过程和动静态链接的区别
linux·服务器·c语言·c++·笔记
剁椒排骨1 分钟前
win11什么都不动之后一段时间黑屏桌面无法显示,但鼠标仍可移动,得要熄屏之后才能进入的四种解决方法
运维·windows·经验分享·计算机外设·win11·win10
angushine3 分钟前
让Docker端口映射受Firewall管理而非iptables
运维·docker·容器
归寻太乙31 分钟前
Linux环境变量
linux·运维·服务器
m0Java门徒32 分钟前
面向对象编程核心:封装、继承、多态与 static 关键字深度解析
java·运维·开发语言·intellij-idea·idea
Sapphire~38 分钟前
Linux-06 ubuntu 系统截图软件使用简单记录
linux·运维·ubuntu
高级IT技术专家secops9981 小时前
在统信UOS/麒麟Kylin OS操作系统中配置APT和GIT代理
运维·服务器·git·系统安全·kylin
工头阿乐1 小时前
Appium自动化开发环境搭建
运维·appium·自动化
自由鬼1 小时前
开源漏洞扫描器:OpenVAS
运维·服务器·安全·网络安全·开源·漏洞管理
難釋懷1 小时前
Shell脚本-while循环语法结构
linux·运维·服务器·bash