我是靠谱客的博主 忧虑咖啡豆,最近开发中收集的这篇文章主要介绍程序员的自我修养读书笔记---动态链接7相比于静态链接,动态链接的内容还是有点多、有点难懂的,尤其是链接时重定位,先了解即可。7.1- 为什么要动态链接(重点了解)7.2- 简单的动态链接的例子(重点了解)7.3- 地址无关的代码(重点了解)7.4- 延迟绑定(PLT)7.5- 动态链接相关结构7.6- 动态链接的步骤和实现7.7- 显式运行时链接,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

相比于静态链接,动态链接的内容还是有点多、有点难懂的,尤其是链接时重定位,先了解即可。

 

7.1- 为什么要动态链接(重点了解

1- 避免浪费内存。加入有两个程序:P_1和P_2,这两个程序都需要用到库LIB_3。如果使用静态链接,则LIB_3都将会被编译到P_1和P_2中。将P_1和P_2运行时,其实上内存中有两份LIB_3。如果使用动态链接,则只需加载一份LIB_3即可。

2- 程序发布变得简单。还是上面例子,如果使用静态链接,LIB_3代码修改了,需要重新编译一份P_1和P_2进行发布,加入P_1依赖的库很多,每个库文件修改,都会导致P_1的重新链接、发布。

如果使用动态编译,则只需发布对应的库文件即可。

 

7.2- 简单的动态链接的例子(重点了解

 

 

7.3- 地址无关的代码(重点了解

装载时重定位:程序在装载时,才对涉及到的无效代码进行重定位。

和地址无关代码(position-indepent-code, PIC):共享对象中需要被修改的指令和数据段放在一块,这样就能保证指令部分不变,数据部分每个进程都有一个副本。

程序中四种类型地址引用:

a- 模块内程序调用、跳转;

b- 模块内数据访问,例如全局变量、静态变量

c- 模块外函数调用

d- 模块外数据访问,例如定义在其他模块的全局变量

书中对这几种类型进行了介绍如何重定位地址。

 

7.4- 延迟绑定(PLT)

基本含义就是:模块加载时并不把模块中所有无效地址重定位,当模块中变量、函数使用时才进行重定位。

 

 

7.5- 动态链接相关结构

P203   动态链接情况下,操作系统再装载完可执行文件后不能将控制权交给可执行文件。因为可执行文件依赖共享对象,这时候,可执行文件里的很多外部符号的引用还处于无效地址状态,即还没有跟相应的共享对象中的实际位置链接起来。所以在映像完可执行文件后,操作系统会先启动动态链接器

linux下动态链接器ld.so也是个共享对象。操作系统以映射的方式将动态链接器加载到内存空间后,控制权交给动态链接器。动态链接器接收控制权后,开始执行自身初始化;然后根据环境参数对可执行文件进行链接;当链接工作完成后,动态链接器会将控制权交给可执行文件,程序正式开始运行。

 

7.6- 动态链接的步骤和实现

动态链接的3个基本步骤:a-启动动态链接器本身; b- 装载所需要的共享对象;  c- 重定位和初始化。

 

a-动态链接器自举(启动动态链接器本身) 

对于一般的共享对象的重定位由动态链接器完成,动态链接器也是一种共享对象,他自己的重定位工作只能由自己完成。

所以动态链接器必须满足两个条件:a- 不依赖其他共享对象; b- 自己完成自己的重定位工作。

动态链接器启动代码不能使用全局、静态变量,这段启动代码称为自举。当动态链接器接收到控制权后,开始运行自举代码。自举代码找到自身需要的重定位表和符号表,并进行重定位工作。完成重定位之前动态链接器不能使用全局、静态变量,以及函数调用。

 

b- 转载共享对象

动态链接器完成自举后,会将自身的符号表和可执行文件的符号表都合并到一块,称为全局符号表

之后,动态链接器寻找可执行文件依赖的共享对象,并将共享对象名字加载到装载集合中。

动态链接器从装载集合中读取共享对象信息,将代码段、数据段映射到进程空间。如果共享对象依赖其他共享对象,则将其依赖的共享对象名字加载到装载集合中。如此循环,直到所有对象都加载进来。

当新的共享对象被加载,他的符号变会被合并到全局符号表中。当所有共享对象加载完成,全局符号表中保存了进程动态链接所需的所有符号

当不同共享对象的符号有相同时,由于全局符号介入的存在,可能后加入共享对象与前加入共享对象重名的符号无法加载到全局符号表。

 

c- 重定位和初始化

当上面步骤完成后,动态链接器开始对涉及到的符号进行重定位。

重定位完成后,如果某个共享对象有“.init”段,那么动态链接器会执行“.init”段中的代码,用来实现对共享对象的初始化。

当重定位、初始化完成后,共享对象已经装载、链接完成,这时候进程控制权转交给程序入口,程序开始执行。

 

linux下的动态链接器为ld.so,其指向/lib/ld-linux.so.2

 

7.7- 显式运行时链接

接口:
dlopen() : 打开动态链接库,返回文件句柄
dlsym() : 打开文件句柄里的符号,返回符号地址、函数名指针,之后就可以返回值访问共享库中接口、变量
dlerror() : 调用dlopen、dlsym、dlclose的异常处理检查
dlclose() :关闭共享库访问

 

 

 

 

最后

以上就是忧虑咖啡豆为你收集整理的程序员的自我修养读书笔记---动态链接7相比于静态链接,动态链接的内容还是有点多、有点难懂的,尤其是链接时重定位,先了解即可。7.1- 为什么要动态链接(重点了解)7.2- 简单的动态链接的例子(重点了解)7.3- 地址无关的代码(重点了解)7.4- 延迟绑定(PLT)7.5- 动态链接相关结构7.6- 动态链接的步骤和实现7.7- 显式运行时链接的全部内容,希望文章能够帮你解决程序员的自我修养读书笔记---动态链接7相比于静态链接,动态链接的内容还是有点多、有点难懂的,尤其是链接时重定位,先了解即可。7.1- 为什么要动态链接(重点了解)7.2- 简单的动态链接的例子(重点了解)7.3- 地址无关的代码(重点了解)7.4- 延迟绑定(PLT)7.5- 动态链接相关结构7.6- 动态链接的步骤和实现7.7- 显式运行时链接所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(82)

评论列表共有 0 条评论

立即
投稿
返回
顶部