
本文共 1798 字,大约阅读时间需要 5 分钟。
一、程序编译/链接/加载/执行环节和工具
二、目标文件(object,也就是.o文件)编译过程
预处理(CPP) --> 编译 --> 汇编 --> 得到.o文件
三、链接过程
1.将object文件和库文件(.o/.a)文件链接成可执行文件的过程
问:.o和.a库文件有什么区别?
答:由很多目标文件进行链接形成的是静态库(.a文件,各个目标之间有依赖关系),静态库也可以简单地看成是一组目标文件(.o)的集合,即很多目标文件经过压缩打包后形成的一个文件,如下图,使用ar命令的-a参数查看静态库的组成:
2.如何决定程序使用动态链接还是静态链接?
(1)通过-Wl,-Bstatic对指定的库使用静态链接
gcc会对-Wl,-Bstatic 后面的库使用静态链接。对-Wl,-Bdynamic后面跟的库使用动态链接。 如果需要对指定的库使用静态链接,其他的库使用默认的动态链接,可以这样用
gcc test -Wl,-Bstatic -lluajit-5.1 -Wl,-Bdynamic -lxxx -lxxx
这样gcc会链接libluajit-5.1.a,而对其他库使用动态链接。
(2)使用 -static 避免动态链接
gcc编译时使用-static参数,会阻止使用动态链接的方式。与之前两个方法不同,-static参数会导致gcc对所有的库使用静态链接,一般不推荐使用这种方式。
3.动态链接和静态链接各有什么优缺点?
静态链接程序占用空间更大,但是执行效率更高;反之,动态链接程序占用空间更小,但是执行效率会低一些。
4.如何查看动态链接程序运行时使用的动态库?
ldd命令(实际上是一个shell脚本),可以使用which ldd命令查看该命令在文件系统中具体位置。
(1)对于静态链接程序而言:对程序使用ldd命令提示不是动态可执行文件
(2)对于动态链接程序而言:对程序使用ldd命令可以看到程序运行时需要的动态库,以及库的路径。
四、Linux elf格式
1.elf是啥意思?
Executable Linkable Format,首先,ELF是Linux下可执行和可链接的文件格式。所以,Linux下.o/.a文件都是elf格式。
2.elf格式
ELF 文件格式把各种信息,分成一个一个的 Section 保存起来。ELF 有一个基本的文件头(File Header),用来表示这个文件的基本属性,比如是否是可执行文件,对应的 CPU、操作系统等等。除了这些基本属性之外,大部分程序还有这么一些 Section:
首先是.text Section,也叫作代码段或者指令段(Code Section),用来保存程序的代码和指令;
接着是.data Section,也叫作数据段(Data Section),用来保存程序里面设置好的初始化数据信息;
然后就是.rel.text Secion,叫作重定位表(Relocation Table)。重定位表里,保留的是当前的文件里面,哪些跳转地址其实是我们不知道的。
最后是.symtab Section,叫作符号表(Symbol Table)。符号表保留了我们所说的当前文件里面定义的函数名称和对应地址的地址簿。
3.elf静态链接过程
链接器会扫描所有输入的目标文件,然后把所有符号表里的信息收集起来,构成一个全局的符号表。然后再遍历elf重定位表,把所有不确定的跳转地址,根据全局符号表各个符号的实际地址,进行一次修正。最后,把所有的目标文件的对应段进行一次合并,变成了最终的可执行代码(CPU可执行)。
在链接器把程序变成可执行文件之后,要装载器去执行程序就容易多了。装载器不再需要考虑地址跳转的问题,只需要解析 ELF 文件,把对应的指令和数据,加载到内存里面供 CPU执行就可以了。
4.elf动态链接过程
在连接器把程序变成可执行文件之后,elf文件的重定位段中还保存着未知地址的符号,这些符号位于动态链接库。在这种情况下,装载器需要考虑地址跳转的问题,并且需要装载器将该可执行文件引用的动态链接库加载到内存,按照上图中静态链接的方法合并多个elf文件的各个段,变成了最终的可执行代码(CPU可执行)。
5.如何查看elf依赖的动态链接库——readelf命令
readelf -d elf_name
参考文章:
发表评论
最新留言
关于作者
