热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

chap77.4延迟绑定

7.3.4共享模块的全局变量问题当一个模块引用了一个定义在共享对象的全部变量的时候,比如一个共享对象定义了一个全部变量global,而模块module.c中是这么引用

7.3.4 共享模块的全局变量问题
当一个模块引用了一个定义在共享对象的全部变量的时候,比如一个共享对象定义了一个全部变量global,而模块
module.c中是这么引用的:

extern int global;
int foo() {
global = 1;
}
当编译器编译module.c时,它无法根据这个上下文判断global是定义在同一个模块的其他目标文件中,还是定义在
另外一个共享对象中,即无法判断是否为跨模块间的调用。

7.3.5 数据段地址无关性
例如有如下代码段:
static int a;
static int* p = &a;

如果共享对象里面有这样一段代码的话,那么指针p的地址就是一个绝对地址,它指向变量a,而变量a的地址会随着
共享对象的装载地址改变巍峨改变,那么如何解决这个问题呢?

对数据段来说,它在每个进程都有一个独立的副本,所以不担心被进程改变,从这点来看,我们可以选择装载时
重定位的方法来解决数据段中绝对地址引用的问题。对于共享对象而言,如果数据段中有绝对地址引用,那么编译器
和链接器就会产生一个重定位表,这个重定位表中包含了“R_386_RELATIVE”类型的重定位入口,用于解决上述问题,
当动态链接器装载共享对象时,如果发现该共享对象有这样的重定位入口,那么动态链接器就会对该共享对象进行
重定位。

实际上,也可以让代码段也使用这种装载时重定位的方法,而不使用地址无关代码。在前面的例子中,为了生成地址
无关代码,在GCC编译的时候,要加上-fPIC参数,这个参数代表产生地址无关的代码段。如果我们不使用这个参数来
产生共享对象又会怎么样呢?例如,用如下命令:
$gcc -shared sample.c -o sample.so
上面这个命令就产生了一个不使用地址无关代码而使用装载时重定位的共享对象,但是如果代码不是地址无关的,那么
它就不能被多个进程之间共享,于是就失去了节省内存的优点。装载时重定位的共享对象的运行速度比使用地址无关代码
的共享对象快,因为它省去了地址无关代码中每次访问全局数据和函数时需要做一次计算当前地址以及间接地址寻址过程。

对于可执行文件来说,如果可执行文件是动态链接的,那么GCC会使用PIC的方法来产生可执行文件的代码段部分,以便于
不同进程能够共享代码段,节省内存。所以我们看到,动态链接的可执行文件中存在“.got”这样的段。

7.4 延迟绑定
动态链接的确有很多优势,但是是以牺牲一部分性能为代价的。据统计ELF程序在静态链接下要比动态链接稍微快些,大约
为1%~5%,主要原因有以下两点:1.动态链接下对于全局变量和静态数据的访问都要进行复杂的GOT定位,然后间接寻址;对于
模块间的调用也要先定位GOT,然后再进行间接跳转。2.动态链接的链接工作在运行时完成,即程序开始执行时,动态链接器
都要进行一次链接工作,例如动态链接器会寻找并装载所需要的共享对象,然后进行符号查找地址重定位工作。

延迟绑定实现
在动态链接下,程序模块之间包含了大量的函数引用,所以在程序开始执行以前,动态链接会耗费不少时间用于解决
模块之间的函数引用的符号查找和重定位。不过在一个函数的执行过程中,很多函数在程序执行完时都不会用到,如果
一开始就把所有函数都链接好实际上是一种浪费。所以ELF采用了一种叫做延迟绑定(Lazy Binding)的做法,基本思想就是
当函数第一次被用到时才进行绑定,如果没有用到则不绑定。
ELF使用PLT(Procedure Linkage Table)的方法来实现。假设liba.so需要调用libc.so中的bar()函数,那么当liba.so中
调用bar()函数时,这时候就需要调用动态链接器中的某个函数来完成地址绑定工作,但是这个函数需要知道一定的信息
来完成绑定过程,例如这个绑定的动作应该针对那个模块中的那个函数进行。
上一节中说道,当调用外部模块的函数时,如果按照通常的做法,应该是通过GOT表中相应的项进行跳转。PLT为了实现延迟
绑定,在这个过程中间又增加了一层间接跳转。调用函数并不直接通过GOT跳转,而是通过一个叫作PLT项的结构来进行跳转。
每个外部函数在PLT中都有一个相应的项,比如bar()函数在PLT中的地址为bar@plt。
ELF将GOT拆分称为两个表,叫做".got"和".got.plt",其中".got"用来保存全局变量引用的地址,".got.plt"用来保存函数引用
的地址,即对于所有外部函数的引用全部被分离出来放到了".got.plt"中,另外".got.plt"还有一个特殊的地方在于它的前三项
是有特殊意义的:
1.第一项保存的是.Dynamic段的地址
2.第二项保存的是本模块的ID
3.第三项保存的是_dl_runtime_resolve()的地址
其中第二项、第三项是由动态链接器在装载共享模块时负责将其初始化,“.got.plt”中其余每一项对应每个外部函数的引用。
我们可以用readelf -S lib.so查看该共享对象的段表,如下图所示:


***图7.4.1***

转:https://www.cnblogs.com/miaoyong/p/3521733.html



推荐阅读
  • 本文介绍了 Go 语言中的高性能、可扩展、轻量级 Web 框架 Echo。Echo 框架简单易用,仅需几行代码即可启动一个高性能 HTTP 服务。 ... [详细]
  • python模块之正则
    re模块可以读懂你写的正则表达式根据你写的表达式去执行任务用re去操作正则正则表达式使用一些规则来检测一些字符串是否符合个人要求,从一段字符串中找到符合要求的内容。在 ... [详细]
  • 本文总结了Java初学者需要掌握的六大核心知识点,帮助你更好地理解和应用Java编程。无论你是刚刚入门还是希望巩固基础,这些知识点都是必不可少的。 ... [详细]
  • 字符串学习时间:1.5W(“W”周,下同)知识点checkliststrlen()函数的返回值是什么类型的?字 ... [详细]
  • 在腾讯云服务器上部署Nginx的详细指南中,首先需要确保安装必要的依赖包。如果这些依赖包已安装,可直接跳过此步骤。具体命令包括 `yum -y install gcc gcc-c++ wget net-tools pcre-devel zlib-devel`。接下来,本文将详细介绍如何下载、编译和配置Nginx,以确保其在腾讯云服务器上顺利运行。此外,还将提供一些优化建议,帮助用户提升Nginx的性能和安全性。 ... [详细]
  • centos 7.0 lnmp成功安装过程(很乱)
    下载nginx[rootlocalhostsrc]#wgethttp:nginx.orgdownloadnginx-1.7.9.tar.gz--2015-01-2412:55:2 ... [详细]
  • Cookie学习小结
    Cookie学习小结 ... [详细]
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • malloc 是 C 语言中的一个标准库函数,全称为 memory allocation,即动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过 malloc 动态分配内存。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • 我有一个从C项目编译的.o文件,该文件引用了名为init_static_pool ... [详细]
  • 文章目录Golang定时器Timer和Tickertime.Timertime.NewTimer()实例time.AfterFunctime.Tickertime.NewTicke ... [详细]
  • MATLAB字典学习工具箱SPAMS:稀疏与字典学习的详细介绍、配置及应用实例
    SPAMS(Sparse Modeling Software)是一个强大的开源优化工具箱,专为解决多种稀疏估计问题而设计。该工具箱基于MATLAB,提供了丰富的算法和函数,适用于字典学习、信号处理和机器学习等领域。本文将详细介绍SPAMS的配置方法、核心功能及其在实际应用中的典型案例,帮助用户更好地理解和使用这一工具箱。 ... [详细]
  • Java中不同类型的常量池(字符串常量池、Class常量池和运行时常量池)的对比与关联分析
    在研究Java虚拟机的过程中,笔者发现存在多种类型的常量池,包括字符串常量池、Class常量池和运行时常量池。通过查阅CSDN、博客园等相关资料,对这些常量池的特性、用途及其相互关系进行了详细探讨。本文将深入分析这三种常量池的差异与联系,帮助读者更好地理解Java虚拟机的内部机制。 ... [详细]
  • 开源实习机会 | Compiler SIG 正式发布实习任务,诚邀您加入申请!
    对编译技术充满兴趣却苦于无从入手?当前疫情形势下,外出实习变得困难重重?现在,Compiler SIG 正式发布了一系列实习任务,为有志之士提供了宝贵的机会。无论你是初学者还是有一定基础的学生,都能在这里找到适合自己的实践项目。我们诚挚邀请您的加入,共同探索编译技术的无限可能! ... [详细]
author-avatar
icrochildren1035_175
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有