我们的应用在从桌面点击App icon 到App展示界面,手机都做了哪些事情?
main函数是如何被调用的?
带着这些问题,研究一下app的启动流程。
首先先普及一些基础概念。
冷启动与热启动
这个概念也是业界提出的名词,其实区别很简单,就看启动之前手机后台是否有app存活。 主要区别:
| 名称 | 区别 |
|---|---|
| 冷启动 | 启动时,App的进程不在系统里,需要开启新进程。 |
| 热启动 | 启动时,App的进程还在系统里,不需要开启新进程。 |
Mach-O
mach-o是iOS/macOS二进制文件的格式,mach-o又分为几种不同的类型。本文介绍了常见的mach-o文件类型以及它们的不同之处。 在Xcode->Build Setting -> Mach-O Type中,我们可以选择下面几种类型:
- Executable(产物为ipa包)
- Dynamic Library(产物为动态库)
- Bundle(产物为bundle文件)
- Static Library(产物为静态库)
- Relocatable Object File(重定向文件)
打开ipa文件:
这个黑瞿瞿的文件就是mach-o格式的可执行文件。
可执行文件生成流程
- 预编译 处理源代码里面以#开头的代码,例如宏定义、import文件、删除注释。
- 编译 词法分析 语法分析 语义分析 生成汇编文件
- 汇编 把汇编代码变成机器命令 生成.o文件
- 链接程序 生成Mach-O文件,把静态库加入到Mach-O的文件中,把动态库信息写入Mach-O的文件。
经过上述步骤,我们开发的代码会生成一个Mach-O格式的可执行文件。详情可阅读这里。
APP启动流程
点击app icon 后,系统调用exec()函数,系统将对应的Mach-O文件加载进内存,同时再将dyld加载进内存。dyld就会进行动态链接。 其中dyld的主要工作有一下几点:
- 递归加载可执行文件所依赖所有动态库
- 进行rebase和bingding操作
- 调用main函数
关于dyld苹果已经开源dyld源码,我们可以通过阅读源码来了解dyld在pre-main阶段的流程。
截止目前(2022年5月)dyld已经更新至dyld4(941)了,iOS15以上系统都是使用的dyld4。在网上找到了dyld3的调用流程图,可以参考。
加载动态库
接下来,可以再看看最新的dyld4启动过程中,关于加载动态库的调用流程。
其中部分源码截图和解析如下:
在objc4源码中的_objc_init 方法处断点,并且使用lldb bt命令查看调用栈。
当然也可以通过查阅libSystem源码和libDispatch源码确认调用关系。
调用_dyld_objc_notify_register来注册3个方法
map_images的调用
来到dyld源码中搜索_dyld_objc_notify_register方法并定位。
继续寻找
setObjCNotifiers方法并定位
可以看到里面对全局变量赋值其实就是保存3个方法,之后调用了
withLoadersReadLock并且传入了block,block内部执行了_notifyObjCMapped。那么block的执行就会调用map_images方法。
可以看到在
withLoadersReadLock是直接调用的。也就是说,map_images是在objc_init的时候就会调用。
load_images的调用
还是在runAllInitializersForMain中。
可以看到加载libSystem还是其他类都用到了这个方法,继续点进去。
其中除了打log外,主要的目的就是调用
_notifyObjCInit,这个值是objc通过_dyld_objc_notify_register传给dyld的,然后在setObjCNotifiers方法中存储的(上面提到过)。
可以看到dyld在加载应用程序的时候也是需要objc的。dyld像是一个首脑派发加载任务给objc,objc把动态库加载进内存。
rebase和bind
mach-o文件中的符号地址都是虚拟地址,在程序启动的时候,系统会生成一个随机数(ASLR),使用虚拟地址加上ASLR才是物理地址,也就是程序正真调用的地址。我们把从虚拟地址换算成物理地址的过程称之为rebase。
可以看到
start中生成了slide这个相当于alsr。
这里也是去处理了
rebase。
调用main函数
通过之前的
prepare就能获取到main函数,之后直接调用。截止目前,我们的程序就进入我们的源代码中了。
写在最后
这篇文章重点是dyld4(dyld-941.5)的源码解析部分,以及为之后的内容做铺垫。很多内容不影响整体理解作者删繁就简,如有遗漏可联系作者。下一遍文章计划对load_images详细讲解。