欢迎你们继续阅读iOS原理探索系列篇章(后续陆续完善补充)html
说到iOS底层原理,相信不少开发童鞋脑子里闪过不少东西,runtime
,KVC
,KVO
,Runloop
等等一系列的词汇,可是不少人没有彻底融汇贯通成为一套体系,我本身也会有这样的烦恼,咱们如何去整合这些原理,由浅入深,由易到难的把这些知识造成知识树,因此才有了这个系列,用来梳理我本身的技能树。git
说到技能树,那就不得不从最基础的东西开始延伸,因此我一开始想到的东西就是程序启动流程,对于iOS开发来讲,咱们的任何程序都是从main
函数开始启动的,那么咱们就先从程序的main
函数开始分析,看看程序启动以前系统到底作了哪些事情。github
这里我新建了一个全新的工程,而且运行起来,在main
函数处打断点,以下图: bootstrap
main
函数执行以前有
start
函数的执行,咱们再看看
start
,以下,能够看到程序在进入
main
函数以前,先执行了
libdyld.dylib
库的
start
函数,再看可能你们就和我同样有些懵逼了,都是一些汇编代码,没有办法去继续看具体的实现了,因此为了清楚的查看具体的细节,接下来给你们介绍一下几个调试方式。
不少时候咱们都会遇到上面的状况,不少系统方法,或者类库,底层实现都没有办法去查看具体细节,这里我在断点调试的地方添加了三个符号断点_objc_init
,libdispatch_init
,libSystem_initializer
,结果以下图: (关于符号断点问题,请查看个人下一篇iOS原理探索系列之alloc&init原理探索里面说明了三种断点调试方法) 数据结构
dyld
,而后分别执行_dyld_start
、dyldbootstrap::start
、dyld::_main
;dyld_sim
的start_sim
、dyld::_main
、开始加载ImageLoader
;libSystem
库的libSystem_initializer
;libdispatch
库的libdispatch_init
、_os_object_init
; -最后来到libobjc
库的_objc_init
完成初始化;整个流程可清晰看到dyld
执行到runtime
初始化以前的调用了。app
根据上面的断点调试细节,咱们能够初步总结App启动main()函数执行前的流程:函数
dyld
库,经过dyld
配置运行环境,加载共享内存、可执行文件(Mach-O
)、动态库、全局C++对象的构造函数的调用、一系列的初始化(runtime
,+load
等)、dyld注册回调函数libSystem
的初始化 libSystem_initializer
libdispatch_init
队列环境的准备_os_object_init
过渡到_objc_init
,以及_dyld_objc_notify_register
镜像文件的映射Runtime
各个部分的原理main
函数这里只是根据断点初步分析,后续会详细分析每一个具体流程底层实现。工具
dyld
dyld(the dynamic link editor)是苹果的动态连接器,在系统内核作好程序准备工做以后,交由dyld负责余下的工做,在App启动时它就负责加载mach-o文件。 它代码是开源的,源码地址。 关于 dyld详细解析说明,可参考dyld详解。oop
Mach-O
Mach-O
文件为Mach Object
文件格式的缩写,它是一种用于可执行文件,目标代码,动态库,内核转储的文件格式。 常见的有如下形式:post
Executable
可执行文件Dylib
动态库和Framework
动态库,对应头文件和资源文件集合Apple可执行文件格式几乎都是Mach-O
;
关于更多Mach-O
,可参考Mac OS X ABI Mach-O File Format Reference(带中文翻译);
关于Mach-O
数据结构,可参考Mac本地路径下的/usr/include/mach-o源码;
为了直观看出Mach-O
相关信息,可使用三方工具MachOView
;
编译好的工程很老了,建议下载源码本身运行使用;
关于安装源码启动报错,可参看别人已经写好的说明,我这边就很少说了;