一、静态连接器ld
静态连接器ld是GNU编译工具链的一部分,包含在binutils中;其中,collect2是对ld的一层包装、我们在静态连接时常用collect2。
静态连接是在程序的编译连接中完成的。
静态连接中,连接器会把引用其他目标文件的函数进行地址重定位、进而分配地址;这叫连接时重定位。
eg:静态库编译进程序就是这样。
二、动态连接器linker
动态连接器linker,是指程序所调用库部分并不是在连接阶段就包含在可执行镜像中;而是在实际运行时由linker连接。这样可以大大提高磁盘及内存的使用效率。
动态连接是在程序装载的过程中完成的。
动态连接中,连接器只是给引用其他目标文件的函数分配一个动态连接符号;地址分配在程序装载时进行,这叫装载时重定位。
eg:程序在执行过程中将共享库链接进进程地址空间就是这样。
我们用readelf -a打开需要用到动态连接的可执行镜像,会发现动态连接器。
arm-none-linux-gnueabi-readelf -a ../../out/target/product/generic/system/bin/testinput
[Requesting program interpreter: /system/bin/linker]
看看ubuntu下的动态链接器:readelf -a main
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
为了提高动态连接效率,出现了延迟绑定的说法:即不是在装载时一次性确定地址,而是在用到某一个变量或函数时、才为该变量或函数重定位地址。
说明:程序是按照一个整体被装载的。
====
补充:
三、动态连接器自举
上面遇到一个问题,和用C语言去编写C编译器一样的问题?
1.动态连接器本身不可以依赖于其他任何共享对象;
2.动态连接器本身所需要的全局和静态变量的重定位工作由它本身完成——在启动时有一段非常精巧的代码、完成动态连接,同时又不能用到全局和静态变量、不可以调用函数。
动态库的静态装载:在可执行文件运行时、进入main函数之前,已经把要用到动态库的变量或函数重定位。
动态库的动态加载:即使用dlopen函数簇,程序初始化完后、直接进入main函数;在需要时才连接。
3.动态链接器linker更新导致的一个HAL加载问题
《Android系统学习》第六章:Android4.1 HAL段错误问题—linker与prelink
本文详细解析了动态连接器与静态连接器在程序编译、连接过程中的区别,包括连接时机、地址分配方式等核心概念,并通过实例展示了如何使用readelf命令查看动态链接器。
3万+

被折叠的 条评论
为什么被折叠?



