You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GOT(全局偏移表)与PLT原理及动态链接相关疑问咨询

动态链接GOT/PLT常见疑问解答

疑问1:两个进程调用同一个共享库时,为什么全局变量不会互相干扰?

首先需要纠正一个普遍的理解偏差:「每个共享库都有自己的GOT」的描述,限定在单个进程的地址空间范围内,不存在跨进程共用的GOT表。
具体原理可以拆解为两点:

  • 共享库的内容分为代码段和数据段两部分:代码段是只读的,会被所有加载该共享库的进程共享,节省内存;但数据段(包含GOT、全局变量等)是每个进程独立的,加载时操作系统会为每个进程创建独立副本。
  • 就算进程没有修改全局变量,初始状态下看起来共享库的全局变量值相同,一旦某个进程修改了该变量,操作系统会触发写时复制(COW)机制,为该进程单独拷贝一份对应的数据页,从此不同进程的该变量完全隔离,不会互相影响。

疑问2:关闭延迟绑定的情况下,为什么还需要PLT,不能直接用GOT处理函数调用?

首先明确一个核心认知:PLT的核心作用不是实现延迟绑定,而是保证共享库代码段的位置无关性、可共享性,统一函数调用的处理逻辑,延迟绑定只是PLT附加实现的优化特性。
我们可以对比变量和函数的处理逻辑差异来理解:

  • 变量访问的逻辑非常简单:编译器直接生成「读取GOT对应条目存储的变量地址 -> 读写该地址」的指令即可,全程不需要修改代码段的任何内容,所有重定位操作都只需要修改属于数据段的GOT,完全不影响代码段的共享。
  • 函数调用如果直接用GOT实现,会存在两个不可忽视的问题:
    1. 指令兼容与编译复杂度问题:如果直接通过GOT做间接调用,编译器需要为共享库内部的函数调用、跨模块的函数调用生成两套完全不同的指令逻辑,部分架构的间接调用指令还会带来额外的性能开销。而PLT是代码段中固定的位置无关桩代码,所有函数调用不管是内部还是外部,都可以走统一的直接调用PLT入口的逻辑,编译逻辑更简单,性能也更稳定。
    2. 无法兼容全局符号介入规则:Linux动态链接默认支持全局符号介入,也就是如果多个模块定义了同名的全局函数,所有对该函数的引用都要绑定到第一个被加载的模块的同名函数上。PLT作为统一的函数调用入口,动态链接器只需要在重定位阶段修改GOT里的地址就能完成符号介入的适配,不需要修改任何代码段内容,保证了代码段的可共享性。
      就算关闭延迟绑定(比如设置环境变量LD_BIND_NOW=1),动态链接器只会在程序启动阶段就把所有GOT条目的函数地址填好,PLT的桩代码只需要直接跳转到GOT指向的地址即可,不需要再走符号解析流程,此时PLT依然存在,承担上述两个核心作用。

内容的提问来源于stack exchange,提问作者algo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 06:39:02