小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
通过问题看本质!!!
APP启动分为两种
冷启动
APP启动前,APP的进程不在系统里,需要系统创建进程分配给APP。 APP进程不在系统里,需要开启新进程。
热启动
APP在冷启动后,用户将APP退到后台,用户重新回到APP。
或者立刻重启,因为进程缓存还存在。
APP进程在系统里,不需要开启新进程。
启动流程三阶段
1、main函数执行之前;
2、main函数执行之后;
3、首屏幕渲染完成后。
二进制重排
二进制重排是main函数执行之前的优化。
APP启动的时候,启动加载的符号是按照Xcode->Targets->Build Phases->Compile Sources的顺序,而不是按照方法调用的顺序。所以我们需要把启动时调用方法的符号获取到,但是要如何获取呢?
- Fishhook无法hook所有的方法,而且需要修改汇编代码,因为参数不确定。
- 静态扫码 :扫描特定段和字节的符号和函数数据。
- 通过clang静态插桩的方式,在编译阶段就在每一个函数的内部二进制数据添加hook代码。
毫无疑问我们用的是clang静态插桩的方式
二进制重排是利用符号的顺序,重新排列代码在文件中的偏移地址,将启动需要加载的方法地址放在前面的页内存中,减少页中断的次数,从而达到优化效果。
APP启动时候使用到的符号,是通过clang静态插桩的方式获取的。在编译阶段就在每一个函数的内部二进制数据添加hook代码,把启动加载用到的符号按顺序写入order文件中,再把路径配置到ld链接器中。这样编译链接的时候就可以按照文件中符号的顺序进行生成对象的mach-o文件。