歡迎你們繼續閱讀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
;
編譯好的工程很老了,建議下載源碼本身運行使用;
關於安裝源碼啓動報錯,可參看別人已經寫好的說明,我這邊就很少說了;