当前位置: 首页 > news >正文

EXPORT_SYMBOL 底层原理

文章目录

    • 前言
    • EXPORT_SYMBOL 工作原理
      • 1、宏定义和预处理
      • 2、内核符号表
      • 3、链接时处理
      • 4、模块加载
    • 详细的过程
      • 1、定义和编译
      • 2、链接阶段
      • 3、加载模块:
      • 4、符号查找:
    • 示例
    • 总结

前言

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

EXPORT_SYMBOL 工作原理

1、宏定义和预处理

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

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

__EXPORT_SYMBOL 又定义为:

#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、定义和编译

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

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

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

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:

// mymodule.c
int my_function(int x) {return x * 2;
}
EXPORT_SYMBOL(my_function);
// 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 的底层原理是通过将符号和符号名存储在特定段中,内核在模块加载时处理这些段并将符号注册到全局符号表,从而实现符号的共享和复用。


http://www.mrgr.cn/news/60708.html

相关文章:

  • 【Linux系统】进程切换与进程的上下文数据
  • 西门子S7-200 SMART 多泵轮换功能库案例下载
  • 面试域——面试系统工程
  • 在数据库访问中,使用localhost、127.0.0.1和IP地址有什么差异
  • Spring boot 配置文件的加载顺序
  • 鸿蒙网络编程系列32-基于拦截器的性能监控示例
  • (蓝桥杯C/C++)—— 编程基础
  • Lomda表达式与函数式接口
  • 爬虫ip与反爬虫的“猫鼠游戏”
  • java基础(Object篇)
  • Python 基础语法 - 赋值运算符
  • auto占位符(C++11~C++17)
  • C语言实现高并发编程——线程池
  • Open3D-Geometry-14:Distance Queries距离查询方法将网格生成为隐式表示
  • 【专题】关系模型的基本理论
  • 使用chatglm API处理论文
  • 排序算法简记
  • 五、Hadoop 分布式文件系统(HDFS)的原理与架构专业解析
  • python 数据结构 1
  • 一文贯通RAG的技术介绍和构建(简易版+附详细代码)
  • 2024年【制冷与空调设备安装修理】考试内容及制冷与空调设备安装修理最新解析
  • Java程序设计:spring boot(12)——定时调度集成 - Quartz
  • 怎么把照片恢复至手机?一文读懂详细教程与多种方法!
  • 从JDK 17 到 JDK 21:Java 新特性
  • 北理工计算机考研难度分析
  • ctfshow(151->154)--文件上传漏洞--.user.ini