通过与 Jira 对比,让您更全面了解 PingCode

  • 首页
  • 需求与产品管理
  • 项目管理
  • 测试与缺陷管理
  • 知识管理
  • 效能度量
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案

25人以下免费

目录

Linux动态链接为什么要用PLT和GOT表

Linux动态链接为什么要用PLT和GOT表

在Linux系统中,动态链接使用PLT(Procedure Linkage Table)和GOT(Global Offset Table)的原因主要涉及动态库的延迟加载、地址空间的优化、以及运行时函数地址的重定向。其中,运行时函数地址的重定向特别关键,因为它允许程序在运行时解析未知的函数地址,实现对动态库函数的有效调用。

一、理解PLT和GOT的作用

首先,我们需要简单理解PLT和GOT在动态链接中承担的角色。PLT(Procedure Linkage Table)提供了一种机制,使得程序在运行时能调用到动态库(如.so文件)中的函数。而GOT(Global Offset Table)则用于存储全局变量和动态链接库函数的地址,使得这些地址可以在程序运行时得到更新。

动态库的延迟加载是指,程序在启动时并不立即加载所有动态库中的函数和变量,而是等到实际运行到需要调用这些函数和变量时,才进行加载。这种方式可以减少程序的启动时间,降低内存占用。PLT和GOT正是实现这一机制的重要工具。

二、动态链接的延迟加载

在程序执行阶段,当首次调用某个动态库中的函数时,由于这个函数的具体地址尚未被解析,程序需要跳转到对应的PLT项,PLT中的指令将引导程序查询GOT,若GOT中该函数的地址仍未解析,就会触发动态链接器(如ld.so)介入,动态链接器负责找到该函数的真实地址,并更新GOT表中的对应项,最后控制权转交到函数的真实地址上。通过这种方式,PLT和GOT配合实现了函数的延迟加载。

三、地址空间的优化

由于可执行文件在编译时不能确定动态库中函数的确切地址,使用PLT和GOT可以在程序运行时解析这些地址。这种机制允许多个程序共享同一动态库的单一物理副本,因此,使用PLT和GOT有助于减少系统的内存使用,提高地址空间的利用率。共享动态库不需要在每个使用它的进程中都有一个副本,从而达到了内存使用的优化。

四、运行时函数地址的重定向

运行时函数地址的重定向是PLT和GOT最关键的功能。当程序在执行过程中第一次调用一个动态库函数时,它实际上是调用了PLT中的一个跳转指令,这个跳转指令进一步引导程序查找GOT中对应的条目。如果该函数的地址还未被解析,动态链接器将会被调用来寻找这个地址,并将其写入GOT中。这个机制确保了即便是在程序运行时,函数的地址也可以被正确地解析和重定向,从而使得动态链接成为可能。

通过PLT和GOT,Linux系统中的动态链接实现了地址的延迟绑定,提供了强大的运行时解析能力,不仅保证了动态库使用的灵活性和方便性,还通过共享机制优化了系统资源的使用。这些机制的设计和实现,使得Linux系统在运行复杂应用程序时,能够高效、灵活地处理不同动态库之间的依赖关系。

相关问答FAQs:

1. 为什么Linux动态链接需要使用PLT表和GOT表?

动态链接是Linux系统中一种常见的技术,它允许多个程序共用一个或多个库文件,提高了代码的重用性。PLT(Procedure Linkage Table)表和GOT(Global Offset Table)表是在动态链接过程中用来实现函数调用的重要数据结构。

2. PLT表和GOT表在Linux动态链接中的作用是什么?

PLT表(Procedure Linkage Table)用于保存动态链接过程中需要调用的各个函数的地址。当程序需要调用一个函数时,它会通过PLT表查找相应函数的地址,然后跳转到该地址执行函数。PLT表的存在可以提高程序执行的效率,避免了每次都进行符号查找。

GOT表(Global Offset Table)则用来存储全局变量和函数的地址。它是用来解决两个问题的:一是减少程序和库的修改,使得它们可以在不同的地址空间中加载;二是减少重定位时的运行时开销,通过在GOT表中存储全局符号的地址,减少了重定位的次数。

3. PLT表和GOT表具体是如何工作的?

当程序进行动态链接时,系统会为每个需要调用的函数生成一个对应的PLT表项,该表项中包含函数的名称和一个跳转指令。当程序第一次调用这个函数时,PLT表中的跳转指令会将控制流程转移到链接器指定的代码段中,然后链接器会通过GOT表来查找函数的真实地址并将其写入到PLT表项中。之后,程序再次调用同一个函数时,会直接跳转到PLT表项中保存的地址,从而实现了对函数的调用。

GOT表的工作原理类似,当程序访问一个全局变量或函数时,会通过GOT表来查找其真实的地址。如果在GOT表中没有找到对应的地址,则会触发一个陷阱(trap),链接器会在运行时从相应的库文件中加载符号的实际地址并更新到GOT表中。

综上所述,PLT表和GOT表在Linux动态链接中起着关键的作用,它们通过提供函数和全局变量的地址信息,实现了程序的动态调用和重定位。

相关文章