首先iOS使用的编译器而非解释器,好处是执行效率高,编译后生成机器码直接在CPU上运行.
iOS使用的编译器是LLVM,他是一个工具链技术的集合,内置lld链接器.
编译过程:预处理(宏命令嵌入)->词法语法分析->AST(抽象语法树)->IR(中间表示)->Mach-O文件.
编译的时候链接器将变量符号(变量名)、函数符号(函数名)跟地址绑定.这个地址是变量、函数的存储地址.绑定的目的是让机器知道你在操作什么内存地址.可执行文件里面装的是数据(全局变量及其值)和代码(函数).
Mach-O文件也有相应的符号和地址,通过链接器合并多个Mach-O文件,就可以调用其它Mach-O文件里的函数了.
链接器连接多个Mach-O文件的时候会生成符号表,记录所有已定义的符号和所有未定义的符号.动态库的符号就会显示“未定义”,动态库的名字和路径会被记录下来.
链接器可以帮助清理未使用的函数,减少Mach-O文件大小.原理是从main函数开始跟随没个引用,将有用的代码标记为live,未标记的就去除掉.
运行时通过dlopen和dlsym导入动态库.
dlopen:它会把共享库载入运行进程的地址空间,载入的共享库也会有未定义的符号,这样会触发更多的共享库被载入.它打开动态库后返回的是引用的指针.
dlsym:它的作用就是通过 dlopen 返回的动态库指针和函数符号,得到函数的地址然后使用。
dyld链接的过程:执行Mach-O文件->根据undefined符号加载动态库->先看看有没有共享缓存,没有就从磁盘加载-> 加载过程开始会修正地址偏移->确定 Non-Lazy Pointer 地址进行符号地址绑定->加载所有类->最后执行 load 方法和 Clang Attribute 的 constructor 修饰函数->main函数返回static terminator.
dyld有两种加载动态库的方式:1、启动的时候 2、第一次使用的时候(可以减少启动时间).
.m文件编译生成.o文件,将.o文件链接生成a.out文件.
静态库:编译的时候链接到Mach-O文件中,想更新库需要重新编译.
动态库:运行时链接的库,可以通过dyld加载. .dylib格式的库就是动态链接的库.
dyld开始于dyldStartup.s(汇编)文件,从dyld_start方法开始.
ImageLoader负责将image加载到内存中.
image:这里指的是二进制文件(可执行文件/so文件),这些文件里是被编译的符号和代码等.