這裏主要剖析一下一個App從點擊圖標,到展示首頁的整個過程。數據庫
按順序劃分緩存
--------- main() ---------安全
didFinishLaunchingWithOptions
)。Apple操做系統使用dyld加載可執行文件。數據結構
dyld全程爲dynomic loader,做用是加載一個進程所須要的Image,在opensource-apple能夠找到它的開源代碼。架構
dyld讀取完Mach-O的Header和Load Commands後,就會找到可執行文件的依賴動態庫。接着dyld會將所依賴的動態庫加載到內存中。這是一個遞歸的過程,依賴的動態庫可能還會依賴別的動態庫,因此dyld會遞歸每一個動態庫,直至全部的依賴庫都被加載完畢。app
加載後的動態庫會被緩存到dyld shared cache中,提升讀取效率。dom
簡單的說下Mach-O,簡單的能夠分爲三個部分,Header,Load Commands,Segment Data。函數
Header中包含的是可執行文件的CPU架構,Load Commands的數量和佔用空間。佈局
Load Commands中包含的是Segment的Header與內存分佈,以及依賴動態庫的版本和Path等。優化
Segment Data就是Segment彙編代碼的實現,每段Segment的內存佔用大小都是分頁頁數的整數倍。
這兩個過程合在一塊兒說,是由於他們之間的工做是相互補充的。
Apple爲了解決應用安全,用到了ASLR(Address space layout randomization 地址空間佈局隨機化)和Code Sign。
App被啓動後,會被映射到虛擬內存中,這樣App在這個空間中就有了一個起始地址,但這個起始地址是固定的。ASLR能使這個起始地址隨機化,這項技術能夠防止攻擊者經過初始地址+偏移量的方法找到函數的內存地址。
Code Sign就是簽名,在進行加密的時候,會對每個Page(這裏指的是Segment Data)都進行加密,當dyld進行加載的時候,會對每個Page都進行獨立的驗證。
Mach-O中採用了PIC(Position Independent Code 地址無關代碼),大當咱們在調用函數時,會在__Data段中創建一個指向該函數的指針,經過這個指針來間接調用。
Mach-O中有不少符號,有些指向當前Mach-O的(咱們爲App編寫的代碼),有些指向其餘DyLib(依賴的動態庫)。
Rebase的做用是從新修正指向當前Mach-O指針的指向,由於上面提到的ASLR將地址隨機化,起始地址不在是固定的,從新修復後,App才能正常運行。
Bind的做用是從新修復外部指針的指向,這個過程會根據字符串匹配的方式來查找符號表,比起Rebase會略慢(這裏fishhook的實現基礎,它在dyld綁定C庫的時候進行了hook)。
由於Objective C的動態特性,因此在Main函數執行以前,須要把類信息註冊到一個全局Table中。同時,Category的方法也會被註冊到對應類中,Category中的同名方法實現,會根據編譯順序,被最後一個編譯的Category實現所覆蓋。同時還會作Selector的惟一性檢測。
這個階段是包含必要的初始化。
這裏區分下+load方法與+Initialize方法,前者是在類加載時調用的,後者是在類第一次收到message以前調用的。
這裏就不作展開了,都是咱們親手寫的代碼。
以上咱們介紹了dyld2的加載方式,在2017WWDC,Apple推出了Dyld3。
Dyld2是從程序開始時纔開始執行的,而Dyld3則將Dyld2的一些過程進行了分解。
Dyld3分爲out-of-process,和in-process。
out-process會作:
in-process會作:
使用了Dyld3後,App的啓動速度會進一步提升
想要了解Dyld的同窗,能夠看看這篇文章App 啓動流程以及優化 WWDC 2017