APP启动流程-dyld
首先,我们先来认识一下Mach-O文件:
一、Mach-O文件
mach-o是iOS/macOS二进制文件的格式,mach-o又分为几种不同的类型。常见的mach-o文件类型有以下几种:
- Executable(产物为ipa包)
- Dynamic Library(产物为动态库)
- Bundle(产物为bundle文件)
- Static Library(产物为静态库)
- Relocatable Object File(重定向文件)
二、可执行文件生成流程
- 预编译 处理源代码里面以#开头的代码,例如宏定义、import文件、删除注释。
- 编译 词法分析 语法分析 语义分析 生成汇编文件
- 汇编 把汇编代码变成机器命令 生成.o文件
- 链接程序 生成Mach-O文件,把静态库、动态库写入Mach-O的文件。
三、APP启动流程
在启动App时,真正的加载过程是从exec()函数开始,系统会调用exec()函数创建进程,并且分配内存。然后会执行以下的操作:
- 把App对应的可执行文件加载到内存。
- 把dyld加载到内存。dyld也是一个可执行的程序
- dyld进行动态链接。
四、dyld的具体工作内容(dyld是开源的)
-
dyld会找到可执行文件的依赖动态库。接着dyld会将所依赖的动态库加载到内存中。这是一个递归的过程,依赖的动态库可能还会依赖别的动态库,所以dyld会递归每个动态库,直至所有 的依赖库都被加载完毕。
-
Rebase和Bind。rebase修复的是指向当前镜像内部的资源指针;而bind指向的是镜像外部的资源指针
-
调起main函数,也就是我们程序的入口,然后我们的程序就开始执行了。
五、dyld的初始化流程
dyld是用来加载可执行文件所依赖的动态库的。然后会对可执行文件和可执行文件所依赖的动态库进行初始化的操作。
在进行初始化的操作的时候首先会初始化libsystem,否则就会报错。因为在进行libsystem初始化的时候,会初始化libdispatch,
在进行libdispatch初始化的时候,会初始化libobjc(这个和runtime相关),其他的库,可能需要依赖runtime基础或者线程相关的基础。
所以libsystem的初始化必须放在第一位。
在libobjc进行初始化的时候,会调用一个_dyld_objc_notify_register函数,这个函数会给dyld传递三个回调函数。
- map_images: dyld将image镜像文件加载进内存时,会触发该函数
- load_images: dyld初始化image会触发该函数
- unmap_image: dyld将image移除时会触发该函数
然后,dyld会调用 map_images 和 load_images 来对image进行初始化的操作。
六、dyld3的调用流程图
七、dyld4的调用过程(https://juejin.cn/post/7097113759251955749#heading-3)