iOS底層探索之dyld(一):動(dòng)態(tài)鏈接器流程分析

1. 前言

現(xiàn)在的互聯(lián)網(wǎng)行業(yè)掸读,是一天比一天卷澡罚,除了底層是必考點(diǎn)了,還有關(guān)于APP的性能優(yōu)化也是面試常問的點(diǎn)催式。

太難了

在優(yōu)化之前必須要對應(yīng)用程序加載的流程熟悉哺窄,那么本次博文就對dyld進(jìn)行底層的初步探索分析坷襟。

在這里插入圖片描述

2. 程序加載原理

2.1 代碼編譯過程

我們都知道代碼編寫完成抱婉,必須通過編譯器編譯才能變成可以執(zhí)行的文件。

程序編譯流程

程序的執(zhí)行,是把可執(zhí)行的文件,加載到內(nèi)存中去執(zhí)行的恕齐,這個(gè)可執(zhí)行的文件(Mach-O)的運(yùn)行必須依賴很多的庫(.a/.lib/.so),庫是可執(zhí)行的二進(jìn)制文件范删,是能夠被加載到內(nèi)存中去的。這些庫,可以分為靜態(tài)庫動(dòng)態(tài)庫

2.2 靜態(tài)庫和動(dòng)態(tài)庫

  • 靜態(tài)庫: 例如.a.framework。靜態(tài)庫鏈接時(shí),會被完整地復(fù)制到可執(zhí)行文件中,被使用到了多次,就會復(fù)制多份,這樣就有多份拷貝很冗余,鏈接時(shí)間長了欢摄,還浪費(fèi)了內(nèi)存空間害捕。
  • 動(dòng)態(tài)庫:例如.dylib.framework盾沫。動(dòng)態(tài)庫鏈接時(shí)凸舵,只會存在一份,并不會復(fù)制多份,在內(nèi)存中共享這一份,系統(tǒng)只加載一次,誰有用到了就去找這一份郊艘,減少了程序的體積大小,可以節(jié)省時(shí)間和內(nèi)存空間。
    靜態(tài)庫和動(dòng)態(tài)庫

    靜態(tài)庫都好理解顶掉,那么動(dòng)態(tài)庫在程序中是怎么加載到內(nèi)存呢茬贵?系統(tǒng)是通過怎樣的方式來鏈接的呢螟左?這就用到了一個(gè)工具,也就是博文開頭提到的dyld(the dynamic link editor)動(dòng)態(tài)鏈接器,

2.3 dyld 動(dòng)態(tài)鏈接器

dyld是iOS操作系統(tǒng)的一個(gè)重要組成部分,在系統(tǒng)內(nèi)核做好程序準(zhǔn)備工作之后暇番,會交由dyld負(fù)責(zé)余下的工作嗤放。
dyld的作用:加載各個(gè)庫,也就是image鏡像文件壁酬,由dyld從內(nèi)存中讀到表中斤吐,加載主程序,link鏈接各個(gè)動(dòng)靜態(tài)庫厨喂,進(jìn)行主程序的初始化工作和措。

程序加載流程

上面這個(gè)圖是dyld的加載工作流程圖,圖中簡單的描述了動(dòng)態(tài)庫注冊和動(dòng)態(tài)庫的加載過程蜕煌,具體分析還得去看底層源碼派阱,那么接下來就去探索分析。

3. 初識dyld

3.1 尋找dyld入口

程序的執(zhí)行我們都知道是從main函數(shù)開始的斜纪,那么dyld在程序的那個(gè)階段執(zhí)行的呢贫母?是在main函數(shù)執(zhí)行前,還是再main函數(shù)執(zhí)行后呢盒刚?這我也不得而知腺劣。

啊因块!你這個(gè)博主橘原,奇奇怪怪的,你寫的博文,你會不知道爸憾稀拒名?

信你個(gè)鬼

這個(gè)嘛,就得探索探索了芋酌!首先建一個(gè)工程將main.m改寫如下:

__attribute__((constructor)) void JPFunc(){
     printf("來了老弟 : %s \n",__func__);
}

int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        NSLog(@"這是main函數(shù)打印");
        // Setup code that might create autoreleased objects goes here.
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

然后運(yùn)行程序增显,打印結(jié)果如下:

來了老弟 : JPFunc 
dyld初探[37212:516752] 這是main函數(shù)打印

這個(gè)__attribute__((constructor))是在main函數(shù)之前執(zhí)行的一個(gè)函數(shù)。

  • 補(bǔ)充:GNU C的一大特色就是__attribute__機(jī)制脐帝。__attribute__可以設(shè)置函數(shù)屬性(Function Attribute)同云、變量屬性(Variable Attribute )和類型屬性(Type Attribute)。

  • __attribute__書寫特征是:__attribute__前后都有兩個(gè)下劃線堵腹,并切后面會緊跟一對原括弧梢杭,括弧里面是相應(yīng)的__attribute__參數(shù)。

  • __attribute__語法格式為:__attribute__ ((attribute-list))

main函數(shù)執(zhí)行之前確實(shí)是可以執(zhí)行其他函數(shù)的秸滴,那么dyld到現(xiàn)在好像還沒有相關(guān)線索武契,那么繼續(xù)往下探索。

main函數(shù)打上斷點(diǎn)

斷點(diǎn)斷在main函數(shù)上

斷點(diǎn)斷在main函數(shù)上荡含,發(fā)現(xiàn)在main之前還調(diào)用了一個(gè)start方法咒唆。

libdyld.dylib`start

點(diǎn)開start是一個(gè)libdyld.dylib start,突然想起網(wǎng)絡(luò)上很流行的一句話释液,歡迎來到德萊聯(lián)盟全释,libdyld.dylib和這發(fā)音好像,哈哈误债!

但是通過對start下符號斷點(diǎn)浸船,斷不住它。說明這不是入口的地方寝蹈,我們知道還有一個(gè)方法+load李命,這個(gè)是在main之前必會調(diào)用的方法,那么就可以在Viewcontroller的寫下+load方法添加斷點(diǎn)箫老,運(yùn)行程序封字。在控制臺輸入指令bt,查看調(diào)用堆棧信息:

堆棧信息

堆棧信息是一個(gè)棧結(jié)構(gòu)耍鬓,先進(jìn)后出阔籽,所以最底下打印的就是最先執(zhí)行的。所以現(xiàn)在我們已經(jīng)找到dyld的入口了牲蜀。

3.2 獲取dyld源碼

_dyld_start笆制,那么這就涉及到底層源碼了,去蘋果開放的源碼官網(wǎng)opensource看看dyld源碼

dyld源碼

我們研究源碼涣达,就得去看最新的蘋果源碼在辆,畢竟技術(shù)更新迭代很快证薇,最新的才是最流行的,也是最香的开缎,研究起來才有味道棕叫,dyld最新的版本是dyld-852林螃,這部分源碼是不能編譯的奕删,但是并不能妨礙我們?nèi)ヌ剿魉D敲次覀儸F(xiàn)在就去打開dyld這個(gè)牛逼的源碼工程一探究竟吧疗认!

3.3 初探dyld 源碼

_dyld_start源碼

全局搜索_dyld_start完残,發(fā)現(xiàn)又是匯編,是不是要瘋了昂崧谨设!
莫慌靚仔,穩(wěn)住缎浇,不會匯編沒有關(guān)系扎拣,請耐心往下看!

dyldbootstrap::start

在匯編里面發(fā)現(xiàn)了一個(gè)重要方法素跺,dyldbootstrap::start二蓝,從紅框中的注釋可以知道,會調(diào)用dyldbootstrap::start這個(gè)C++函數(shù)指厌,那么就可以去全局搜索下刊愚,看看C++函數(shù)的命名空間。

namespace dyldbootstrap

從命名空間里面踩验,我們可以找到start

在這里插入圖片描述

start函數(shù)里面返回的是dyld::_main鸥诽,這就nice了,突然就很熟悉箕憾,很親切牡借。

博文篇幅有限,下篇繼續(xù)探索袭异。蓖捶。。扁远。俊鱼。
iOS底層探索之dyld(下):動(dòng)態(tài)鏈接器流程源碼分析

4. 總結(jié)

  • 應(yīng)用程序加載到內(nèi)存中運(yùn)行,會通過dyld鏈接各種庫
  • 庫分為動(dòng)態(tài)庫靜態(tài)庫
  • 靜態(tài)庫有多份拷貝畅买,增加包的大小并闲,程序加載鏈接時(shí)間長,浪費(fèi)了內(nèi)存空間谷羞。
  • 動(dòng)態(tài)庫存在一份帝火,并不會復(fù)制多份溜徙,節(jié)省程序加載鏈接時(shí)間和內(nèi)存空間
  • iOS的可執(zhí)行的文件是Mach-O
  • dyld源碼可以去蘋果的開源opensource查看

更多內(nèi)容持續(xù)更新

?? 喜歡就點(diǎn)個(gè)贊吧????

?? 覺得學(xué)習(xí)到了的,可以來一波犀填,收藏+關(guān)注蠢壹,評論 + 轉(zhuǎn)發(fā),以免你下次找不到我?? ??

??歡迎大家留言交流九巡,批評指正图贸,互相學(xué)習(xí)??,提升自我??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末冕广,一起剝皮案震驚了整個(gè)濱河市疏日,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撒汉,老刑警劉巖沟优,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異睬辐,居然都是意外死亡挠阁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進(jìn)店門溯饵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侵俗,“玉大人,你說我怎么就攤上這事瓣喊∑禄牛” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵藻三,是天一觀的道長洪橘。 經(jīng)常有香客問我,道長棵帽,這世上最難降的妖魔是什么熄求? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮逗概,結(jié)果婚禮上弟晚,老公的妹妹穿的比我還像新娘。我一直安慰自己逾苫,他們只是感情好卿城,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著铅搓,像睡著了一般瑟押。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上星掰,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天多望,我揣著相機(jī)與錄音嫩舟,去河邊找鬼。 笑死怀偷,一個(gè)胖子當(dāng)著我的面吹牛家厌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播椎工,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼饭于,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了晋渺?” 一聲冷哼從身側(cè)響起镰绎,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤脓斩,失蹤者是張志新(化名)和其女友劉穎木西,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體随静,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡八千,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了燎猛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恋捆。...
    茶點(diǎn)故事閱讀 39,764評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖重绷,靈堂內(nèi)的尸體忽然破棺而出沸停,到底是詐尸還是另有隱情,我是刑警寧澤昭卓,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布愤钾,位于F島的核電站,受9級特大地震影響候醒,放射性物質(zhì)發(fā)生泄漏能颁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一倒淫、第九天 我趴在偏房一處隱蔽的房頂上張望伙菊。 院中可真熱鬧,春花似錦敌土、人聲如沸镜硕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兴枯。三九已至,卻和暖如春犬金,著一層夾襖步出監(jiān)牢的瞬間念恍,已是汗流浹背六剥。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留峰伙,地道東北人疗疟。 一個(gè)月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像瞳氓,于是被迫代替她去往敵國和親策彤。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容