iOS應用啟動流程分析之dyld過程初探

語言: CN / TW / HK

theme: fancy highlight: agate


前言:作為一個開發者,如果你熟悉很多語言的開發,你會發現大部分語言的一個共同點,main函式。我們都是從main函式開始,去關注程式的編寫、編譯和執行過程。main函式之前,系統有沒有做一些其他的工作,做了哪些工作呢,一起來看看?

一、應用啟動分析

1、程式從編寫到執行的過程

編譯過程.png

1、程式碼怎麼載入到記憶體?

2、靜態庫、動態庫怎麼載入到記憶體?

3、objc_init -> objc 在哪裡執行的?

我們可以想一下以上的過程是怎麼發生的,各個環節都是怎麼載入到記憶體的?

2、靜態庫和動態庫

我們經常在專案中使用靜態庫和動態庫,其中系統提供的UIKit,Foundation庫,WebKit庫等等,這些是動態庫,比如我們經常使用的自定義的靜態Framework,.a檔案,就是屬於靜態庫。那麼,靜態庫和動態庫是怎麼區分的?

靜態庫和動態庫.png - 動態庫形式:.dylib和.framework

  • 靜態庫形式:.a和.framework

    如上圖所示,我們分析:

    1、靜態庫:連結時,靜態庫會被完整地複製到可執行檔案中,被多次使用就有多份冗餘拷貝

    2、動態庫:連結時不復制,程式執行時由系統動態載入到記憶體,供程式呼叫,系統只加載一次,多個程式共用,節省記憶體

    但是,系統的動態庫怎麼載入到記憶體呢?通過什麼方式?這裡就用到了一個工具dyld動態連結器。

3、動態連結器

3.1 動態連結器的工作過程

dyld載入.png

上面是dyld的載入工作流程圖,通過它主要進行了動態庫的註冊和動態庫的載入過程。

二、dyld過程初探

  • 通過上面原理的整體分析後,我們接下來就進行應用程式程式碼執行邏輯的分析

image.png

在main函式的入口位置,加上斷點,執行後程序停在斷點位置,經過堆疊列印(bt為lldb堆疊列印命令),發現程式是崩潰在了lldb中,這裡我們並不能獲取更多資訊去跟蹤。

於是,我們通過程式設計經驗,想到了在程式執行main函式之前,會提前執行load函式的載入,那麼就做一下嘗試,在ViewController中假如load函式,並新增斷點,執行程式。

image.png

結果很順利,我們斷點停在了ViewController的load方法,通過堆疊列印,發現了關於dyld的一系列函式過程。下面就引出我們探究的主題:dyld(動態連結器),我們的函式追蹤,也將按照這樣一個順序去進行!

1、dyld簡介

dyld(the dynamic link editor)是蘋果的動態連結器,是蘋果作業系統一個重要組成部分,在系統核心做好程式準備工作之後,交由dyld負責餘下的工作。而且它是開源的,任何人可以通過蘋果官網下載它的原始碼來閱讀理解它的運作方式,瞭解系統載入動態庫的細節。

2、dyld的原始碼

蘋果官方 dyld庫 下載地址

image.png

這裡我們選擇最新的版本進行研究,技術嘛,總要與時俱進,下載完這些,先不急,先來一個蘋果的官方影片介紹,關於dyld2,到dyld3過程的更新、特性,然後我們在下一章介紹 dyld 的探究過程。

3、蘋果官方關於dyld的介紹影片

App Startup Time: Past, Present, and Future https://developer.apple.com/videos/play/wwdc2017/413/

三、總結

我們這裡介紹了應用啟動過程的大概過程分析,主要有:

1、動態庫與靜態庫的概念和理解

2、dyld的概念和連結過程解析

3、我們是如何知道程式是在main函式之前進入了dyld

關於dyld的詳細執行過程,下一節單獨講解!

連結:iOS應用啟動流程分析之dyld原始碼解析

🌺更多內容期待與你一起分享,喜歡的話,點個贊點個關注,持續為您創造好的內容。