Main调用之前的加载过程

2018-03-10  本文已影响127人  繁星mind

1.系统加载可执行文件(自身app的所有.o文件的集合)

2.加载动态链接器dyld,dyld从可执行文件的以来开始,递归加载动态链接库

3.动态链接库包括所有用到的framework,加载runtime的libobjc,系统libSystem,例如:GCD和block的库

4.动态链接库的加载步骤具体分为5步:
load dylibs image 读取库镜像文件
Rebase image
Bind image
Objc setup
initializers

1)load dylibs image
分析所依赖的动态库
找到动态库的mach-o文件
打开文件
验证文件
在系统核心注册文件签名
对动态库的每一个segment调用mmap()

2) rebase/bind
rebase修复的是指向当前镜像内部的资源指针; 而bind指向的是镜像外部的资源指针。 rebase步骤先进行,需要把镜像读入内存,并以page为单位进行加密验证,保证不会被篡改,所以这一步的瓶颈在IO。bind在其后进行,由于要查询符号表,来指向跨镜像的资源,加上在rebase阶段,镜像已被读入和加密验证,所以这一步的瓶颈在于CPU计算。

3)Objc setup
注册Objc类 (class registration)
把category的定义插入方法列表 (category registration)
保证每一个selector唯一 (selctor uniquing)

4.)initializers
Objc的+load()函数
C++的构造函数属性函数 形如attribute((constructor)) void DoSomeInitializationWork()
非基本类型的C++静态全局变量的创建(通常是类或结构体)(non-trivial initializer) 比如一个全局静态结构体的构建,如果在构造函数中有繁重的工作,那么会拖慢启动速度

load的加载过程:
1)dyld 开始将程序二进制文件初始化
2)交由 ImageLoader 读取 image,其中包含了我们的类、方法等各种符号
3)由于 runtime 向 dyld 绑定了回调,当 image 加载到内存后,dyld 会通知 runtime 进行处理
4)runtime 接手后调用 mapimages 做解析和处理,接下来 loadimages 中调用 callloadmethods 方法,遍历所有加载进来的 Class,按继承层级依次调用 Class 的 +load 方法和其 Category 的 +load 方法

参考资料:
https://techblog.toutiao.com/2017/01/17/iosspeed/
https://blog.sunnyxx.com/2014/08/30/objc-pre-main/

上一篇下一篇

猜你喜欢

热点阅读