《程序员的自我修养——链接、装载与库》读书笔记(1)

         这两天看了《程序员的自我修养——链接、装载与库》一书的前三章,感觉还是很有收获的。虽然这本书对于开发一个现成的app来说,貌似没什么作用,但对于理解一个系统软件到底是如何从高级语言代码到跑在硬件上的程序还是很有帮助的。

         大部分人都知道我们写的代码要经过预处理、编译、汇编成目标文件,然后经过链接生成最终的可执行文件,但是细节上是怎么一回事就懒得管了。编译的过程我还算有点了解,什么词法分析、语法分析、语义分析之类一系列复杂的步骤,最终得到目标文件,然而链接就完全不知道是怎么一回事了。读这本书前,我曾经一直以为目标文件就是一系列机器码,链接就是把一些库函数嵌入进去,然后程序就可以跑了。直到书中提了一个问题:不同文件中互相调用函数或者全局变量的时候如何确定地址呢?再仔细想,那些调用了别的文件中函数或全局变量的目标文件该如何区分这些变量和自己文件内的静态变量?我顿时感觉链接的过程并没有那么简单,而且目标文件应该也不仅仅是我们写的代码对应的机器码而已,应该也包含了关于函数、变量的信息,而如果要把这一切组织起来,需要更严谨、有效率的文件结构,这就是COFF文件,即Windows上的PE文件和LinuxELF文件。

         以ELF文件为例,其中包含了文件头、代码段、数据段、bss段、段表、重定位表、字符串表、符号表这几个核心部分以及其他调试信息之类的段。文件头包含了这个ELF文件的信息,如文件类型、文件大小、硬件平台、段表地址等;代码段放机器码,数据段放已定义的静态变量,bss段放未定义的静态变量;段表记录了每个段的地址、大小、类型等信息;重定位表记录了需要重定位(绝对地址引用)的变量与函数的信息;字符串表包含了整个ELF文件中的所有字符串;符号表对代码中出现的符号进行记录,变量、函数、段名及一些特殊符号。

          整个ELF文件相当于对我们的程序进行了一个全方位的分析,并用了一套非常高效的数据结构记录下程序信息,这种方式最吸引人的一点是,所有目标文件、共享文件和可执行文件都用这种格式来记录数据,这样统一简洁的方式使得将几个目标文件拼接、裁剪变得容易许多,或者说链接这个步骤不会再像上头说得那样难以捉摸。

          虽然我还没有看到链接的部分,但是我大体可以猜测到链接的核心过程:针对重定位表中的变量名和函数名在其他文件中找寻相应的变量和函数,找到后本文件中的变量和函数地址指向包含其内容的地址;然后最重要的一点,将所有文件安排到一个虚拟地址空间中,每个段在文件中相对偏移以及每个段中段内元素的相对偏移都已经在各自编译时确定好,连接时只要确定每个文件的基址就行了。当然这只是我的猜测,具体究竟是怎样的机制还要接下来再看了。

         除了上面说的有趣的内部机制,书上还提到了符号表中符号修饰的相关内容,这也让我对C++C之间有了新的了解,我曾以为C++能够完全兼容C,看了书才知道,C++中的符号修饰机制与C不同以至于C的库是不能直接给C++用的,必须使用条件宏这样的小把戏。还有些关于强弱定义与强弱引用的内容,可以算是C项目开发时的实用技巧,对任何一种语言来说都是一种借鉴。


猜你喜欢

转载自blog.csdn.net/weixin_41685679/article/details/79477618