1、APP启动时间
1)main之前的系统dylib(动态链接库)和自身App可执行文件的加载的时间
2)main之后执行didFinishLaunchingWithOptions:结束前的时间
2、main之前的加载过程
1)首先加载可执行文件(自身app的所有.o文件集合)
2)然后加载动态链接库dyld,dyld是一个专门用来加载动态链接库的库
3)执行从dyld开始,dyld从可执行文件的依赖开始,递归加载所有的依赖动态链接库
4)动态链接库包括:iOS中用到的所有系统的framework,加载OC runtime方法的libobjec,系统级别的libSystem,例如libdispatch(GCD)he libsystem_blocks(Block)
5)dyld:the dynamic link editor,所有动态链接库和我们App的静态库.a和所有类文件编译后.o文件,最终都由dyld加载到内存的
3、动态链接库库是相对于系统来讲的
4、可执行文件是相对于App本身来讲的
5、每个app 都是以镜像为单位进行加载的
1)镜像(Mirroring)是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。
2)镜像是一种文件存储形式,可以把许多文件做成一个镜像文件。
3)每个镜像又都有个ImageLoader类来负责加载,一一对应的关系
6、framework 是动态链接库和相应资源包含在一起的一个文件结构
7、系统使用动态链接库的好处
1)代码共用:很多程序都动态链接了这些lib,但它们在内存和磁盘中只有一份
2)易于维护:由于被依赖的lib是程序执行时才链接的,所以这些很容易更新,只要保证在程序执行之前,获取最新lib即可
3)减少可执行文件体积:相比静态链接,动态链接在编译时不需要打进去,所有可执行文件的体积要小很多
8、动态链接库的加载步骤具体分为5步
1)load dylibs image 读取库镜像文件
2)Rebase image 重定位镜像
3)Bind image 组装镜像
4)Objc setup 设置对象
5)initializers 初始化
9、第一步又分为下面6个过程
1)分析所依赖的动态库
2)找到动态库的mach-o 文件(我们知道Windows下的文件都是PE文件,同样在OS X和iOS中可执行文件是Mach-o格式的。)
3)打开文件
4)验证文件
5)在系统核心注册文件签名
6)对动态库的每一个segment调用mmap()
10、8.2,8.3
由于ASLR(address apace layout randomization)的存在,可执行文件和动态链接库在虚拟内存中的加载地址每次启动都不固定,所以需要这两步俩修复镜像中的资源地址,来纸箱正确的地址
1)rabase 修复的是指当前镜像内存的资源指针;bind指向的是镜像外部的资源指针
2)rebase步骤先进行,需要把镜像读入内存,并以page为单位进行加密验证,保证不会被篡改;bind 在其后进行,由于要查询表符号表,来指向镜像的资源;
11、8.4
- 注册objc类
2)把category的定义插入方法列表
3)保证每个selector唯一
12、8.5
0)以上三步属于静态调整(fix up),都是在修改__DATA segment中内容,从这里开始动态调整,开始在堆和堆栈写入内容
1)objc 的 + load 函数
2)C++的构造函数属性函数 形如 attribute((contructor))void DoSomeInitializationWork()
3)非基本类型的C++静态全局变量的创建(通常是类或结构体)(non-trivial initializer)重大初始化
13、再次回顾整个调用顺序
1)dyld 开始将程序二进制文件初始化
2)交由ImageLoader 读取 image,其中包含了我们的类,方法等各种符号(Class、Protocol 、Selector、 IMP)
3)由于runtime 向dyld 绑定了回调,当image加载到内存后,dyld会通知runtime进行处理
4)runtime 接手后调用map_images做解析和处理
5)接下来load_images 中调用call_load_methods方法,遍历所有加载进来的Class,按继承层次依次调用Class的+load和其他Category的+load方法
6)至此 所有的信息都被加载到内存中
7)最后dyld调用真正的main函数
8)注意:dyld会缓存上一次把信息加载内存的缓存,所以第二次比第一次启动快一点
简单的回答:
1.动态库链接库
2.ImageLoader加载可执行文件, 里边是被编译过的符号,代码等
3.runtime与+load