连接器负责的工做:ios
地址绑定、重定位、库查询、代码分段函数
加载器负责的工做:blog
重定位(先因为硬件重定位而省略)内存
地址绑定:字符串
将更抽象的名字与更底层的名字绑定(如getline名字绑定到iosys模块内可执行代码的612字节处,或这个模块静态数据开始的第405字节处)。get
重定位:编译器
编译器和汇编器生成的目标代码地址从0开始。一个程序有多个子程序组成,子程序们的地址不能重叠。重定位就是为程序不一样部分分配加载地址,调整程序中的数据和代码以反映所分配地址的过程。数学
重定位通常不止一次,连接时,各子程序经过重定位在大程序中肯定位置。当程序加载时,系统会选择一个加载地址,而连接好的程序会做为总体被重定位到加载地址。io
符号解析:编译
当多个子程序构建一个大程序时,子程序间互相做用是经过符号进行的,如主程序调用sqrt,sqrt定义在数学库中。连接器经过标明分配给sqrt的地址来解析这个符号,并修改目标代码使得call指令引用该地址。
程序加载:
将程序从辅助存储器拷贝到内存中,准备运行。有些状况下,还包括分配存储空间,设置保护位,或经过虚拟内存将虚拟地址映射到磁盘内存页上。
当容许一个程序的多个实例时,程序中的某些部分在全部的容许实例中都是相同的(尤为时可执行代码),而另外一些部分是各实例独有的。
编译连接实例
m.c
m包含程序段16B,数据段16B(字符串)
符号表:_main(导出符号)、_a(导入符号)
程序先将字符串的地址压栈,用于传参。
在调用a函数时,因为a未知,因此用0x0代替地址,并作好标记。
a.c
a.c程序段0x1c字节
其中调用的库函数都是未知的因此用0x0代替入口地址
使用静态连接
连接后数据段变多,是因为使用静态连接库函数
程序增长了启动代码start-c,和调用的库函数例程
_c和_main符号都从新进行地址绑定。
能够看出静态连接会复制导入的符号相关的实例,这就形成了程序体积会很大