简介
程序员编写的是源代码,而计算机运行的则是 CPU 能辨认的机器指令,因而必须要有一系列工具或程序来将源代码转化为机器指令,这个转化的过程须要经验编译和链接两个次要阶段。所谓编译就是将源代码文件转化为两头的指标文件 (Object file)。指标文件的后缀个别为.o。iOS 零碎的指标文件也是一种 mach- o 格局的文件,mach- o 文件的头部构造体:struct mach_header 中的 filetype 成员字段用来形容以后文件的类型,指标文件所对应的类型是 MH_OBJECT。指标文件中的布局构造和内容和可执行文件中的布局构造和内容十分类似,编译后造成的指标文件中的代码段(__TEXT Segment) 中的节(__text Section) 中的内容寄存的是曾经被编译为机器指令的二进制代码了。
iOS 开发交换技术群:563513413,不论你是大牛还是小白都欢送入驻,分享 BAT, 阿里面试题、面试教训,探讨技术,大家一起交流学习成长!
动态库和动静库的存在模式
- 动态库:.a 和 .framework
- 动静库:.dylib 和 .framework
动态库和动静库的区别
- 动态库:链接时,动态库会被残缺地复制到可执行文件中,被屡次应用就有多份冗余拷贝
- 动静库:链接时不复制,程序运行时由零碎动静加载到内存,供程序调用,零碎只加载一次,多个程序共用,节俭内存
- 上面就是一个指标文件的布局构造:
image.png
重定位表(Relocation table)
零碎的编译操作是针对一个个源文件的独立行为。通常状况下在编写程序时会援用其余源文件或者动静库中定义的函数或者类办法以及全局变量,因而在编译阶段所有的内部援用符号的地址是无奈被确定的,此时生成的指标文件中的段 (Segment) 中的节 (Section) 中的内部函数调用指令的操作数局部以及内部全局变量符号的地址的值都将是 0。在后续的链接过程中须要调整这些指令的操作数的值来进行重定位 (Relocation),为此零碎在编译的指标文件中的对那些有内部符号援用的节(Section) 中都会建设一个重定位表(Relocation table)。这个重定位表中的每个条目会将所有须要进行重定位的指令或者数据拜访的地位信息以及援用的内部符号的信息记录起来,以便在链接时进行更新解决。上面的图表展现了这个构造:
image
简要的说一下链接步骤所做的事件
当编译器对所有的源代码文件编译实现后,接下来的步骤就是链接了。链接的次要性能就是将所有指标文件中的各个雷同段和节的信息顺次连接起来拼装成一个独自的可执行文件。同时还会将所有指标文件中须要 Relocation 的局部的指令进行调整,因为此时能够晓得每个援用符号的地位了。在链接时零碎会剖析每个指标文件中的依赖信息,也就是说链接成一个可执行文件中各段各节的内容总是无依赖的指标文件放在后面而有依赖的指标文件搁置在前面。
动态库的作用
每当咱们 build 一个工程项目时,零碎总是会先将所有源代码编译为指标文件,再将指标文件链接为可执行程序。即便是咱们扭转其中某一个文件中的源代码,而其余文件没有扭转也是如此。因而为了放慢编译速度,有些文件将不再以源代码的模式提供,而是能够将一部分指标文件先集中起来造成一个动态库。这样就能够对这部分文件略过编译而间接进行链接从而放慢编译的速度。
对于 iOS 零碎来说因为不反对第三方以动静库的模式集成到咱们的工程中以及上传到 appstore。而第三方提供的库因为平安和知识产权以及窃密的个性不大可能以源代码的模式提供给咱们,而是以动态库的模式提供给咱们。
可见动态库的作用次要是为了放慢编译速度、进行模块划分、以及代码平安的性能。动态库是一个编译产生的后果,而动静库则是编译链接产生的后果。动态库的组成其实是一个个指标文件。