我们的使用在从桌面点击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_ini
t的时分就会调用。
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
详细解说。
参阅链接
-
iOS App发起优化(一)—— 了解App的发起流程
-
iOS安全:Mach-O Type
-
了解iOS app的编译,运转进程
-
iOS APP 发起优化(七):dyld 加载流程详细分析
-
深化了解Mach-O文件中的Rebase和Bind
-
iOS 底层系列 – ALSR地址空间布局随机化