操作系统学习笔记-链接

    对于我们经过信心苦苦开发过后完成的代码往往需要经过编译,汇编,链接之后才能形成可执行的代码。其中链接过程指的是将程序所需要的代码与资源集成到一个可执行文件中的过程。其中链接过程能够发生在编译过程中,加载时和运行时,在这三种情况下的链接过程都有一定的差别。并且这三种链接过程与连接器处理的三种目标文件类型相关,他们分别为可重定位的目标文件,可执行的目标文件和共享的目标文件。下面来详细分析三种链接过程。

    首先对于发生在编译过程中的链接过程,这也是在编码之后经常会用到的链接过程,经过编译之后的文件被组织成了可重定位的目标文件格式。对于每个可重定位的目标文件,代码,数据,声明等信息以分段的形式存储于目标文件中。其中代码存储于代码段中,对应于全局变量或者方法的引用在这里被作为符号存储于符号段中,诸如此类各种信息呗存储于其所对应的段中。链接过程首先要做的便是进行符号的解析。所谓的符号解析过程便是将代码中的全局变量,方法等对应到符号表中的具体符号,以便后期利用符号替换为真正的内存地址。在完成符号的解析过程后便可以进行重定位,首先将各个目标文件的各个分段合并成一个,形成一个单独的可执行目标文件,之后便能够为符号表中的各个符号制定内存地址,这样之后每个全局变量,全局方法都会有自身的内存地址。最后将真实的变量和方法的引用替换为主存储器的地址便完成了整个连接过程,这样在可执行目标文件执行的过程中就能够直接利用主存储器地址运行相应的代码或者读取所需变量的值了。在这过程中不难发现一个问题,既然是先进行编译之后才进行连接,那么对于全局变量或者方法的非本地连接在编译过程中如何处理。编译器采取的策略是利用被称为重定位条目的数据结构在相应的引用处起到一个占位符号的作用,在连接完成之后进行替换。

    在实际的应用中编译过程连接并不能完全满足我们的需要,动态连接共享库在实际应用中广泛使用。人们将常用的功能或者代码编译好之后使之以共享目标文件的形式存在,再将多个共享目标文件打包形成共享库,在编写的代码中只需要引用共享库中的功能,但是在编译连接过程中并不把共享库中的代码连接致可执行目标文件中,而是在可执行目标文件载入内存时根据引用的内容在内存中将共享目标文件载入某个特定段中,这时再利用重定位条目重定位对于共享目标文件的引用,使之能够访问对应的引用,这样在运行时就能完整的完成程序的功能,而且有效的节省了主存储器的空间。这种连接过程便是加载时连接。

    最后一种连接形式更为灵活,那就是在运行时进行连接。运行时连接所涉及到的主要内容便是与位置无关代码,由于已经存在于内存中的程序需要对另一共享目标文件进行引用,然而此时目标文件有可能并未加载至内存,所以自然无法得知引用地址,但这时可以将共享目标文件加载,其内部代码是与位置无关的,所谓的与位置无关指的是代码内任何数据的存储地址与其代码值的差值是固定的,此时仅需维护一个每个变量位置与代码位置差值表,因此仅仅需要根据当前PC值利用这个差值进行一步转换便能够得到真正的目标地址,然而每次访问变量都进行一次转换显然增加了系统的负担,因此系统维护了另外一个变量与其绝对地址的映射表,当第一次访问特定变量之后其绝对地址便会存储致表中,之后的访问只需查找这个映射表即可。

    以上便是对全部连接过程的理解,所需注意的地方便是加载时连接,其连接顺序是根据命令从左向右进行连接,所以共享目标文件一定要在最后,否则会出现连接错误。

猜你喜欢

转载自piaolingyu.iteye.com/blog/1545277
今日推荐