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

什么是庫 ?

庫就是程序代碼的集合嫂易,將N個(gè)文件組織起來,是共享程序代碼的一種方式掐禁。庫從本質(zhì)上來說是一種可執(zhí)行代碼的二進(jìn)制格式怜械,可以被載入內(nèi)存中執(zhí)行。

庫的分類

  • 開源庫:源代碼是公開的傅事,可以看到每個(gè)實(shí)現(xiàn)文件(.m文件)的實(shí)現(xiàn)缕允,例如GitHub上的常用的開源庫:AFNetworking、SDWebImage等享完;

  • 閉源庫:不公開源代碼灼芭,是經(jīng)過編譯后的二進(jìn)制文件,看不到具體的實(shí)現(xiàn)般又。閉源庫又分為:靜態(tài)庫 和 動(dòng)態(tài)庫

    1彼绷、linux中靜態(tài)庫和動(dòng)態(tài)庫區(qū)別:

    庫從本質(zhì)上來說是一種可執(zhí)行代碼的二進(jìn)制格式,可以被載入內(nèi)存中執(zhí)行茴迁。庫分靜態(tài)庫和動(dòng)態(tài)庫兩種寄悯。

    靜態(tài)庫:這類庫的名字一般是libxxx.a;利用靜態(tài)函數(shù)庫編譯成的文件比較大堕义,因?yàn)檎麄€(gè)函數(shù)庫的所有數(shù)據(jù)都會(huì)被整合進(jìn)目標(biāo)代碼中猜旬,他的優(yōu)點(diǎn)就顯而易見了,即編譯后的執(zhí)行程序不需要外部的函數(shù)庫支持倦卖,因?yàn)樗惺褂玫暮瘮?shù)都已經(jīng)被編譯進(jìn)去了洒擦。當(dāng)然這也會(huì)成為他的缺點(diǎn),因?yàn)槿绻o態(tài)函數(shù)庫改變了怕膛,那么你的程序必須重新編譯熟嫩。

    動(dòng)態(tài)庫:這類庫的名字一般是libxxx.so;相對于靜態(tài)函數(shù)庫,動(dòng)態(tài)函數(shù)庫在編譯的時(shí)候 并沒有被編譯進(jìn)目標(biāo)代碼中褐捻,你的程序執(zhí)行到相關(guān)函數(shù)時(shí)才調(diào)用該函數(shù)庫里的相應(yīng)函數(shù)掸茅,因此動(dòng)態(tài)函數(shù)庫所產(chǎn)生的可執(zhí)行文件比較小。由于函數(shù)庫沒有被整合進(jìn)你的程序柠逞,而是程序運(yùn)行時(shí)動(dòng)態(tài)的申請并調(diào)用昧狮,所以程序的運(yùn)行環(huán)境中必須提供相應(yīng)的庫。動(dòng)態(tài)函數(shù)庫的改變并不影響你的程序板壮,所以動(dòng)態(tài)函數(shù)庫的升級比較方便逗鸣。

    2、iOS開發(fā)中靜態(tài)庫和動(dòng)態(tài)庫區(qū)別:

    靜態(tài)庫和動(dòng)態(tài)庫是相對編譯期和運(yùn)行期的:靜態(tài)庫在程序編譯時(shí)會(huì)被鏈接到目標(biāo)代碼中,程序運(yùn)行時(shí)將不再需要改靜態(tài)庫慕购;而動(dòng)態(tài)庫在程序編譯時(shí)并不會(huì)被鏈接到目標(biāo)代碼中聊疲,只是在程序運(yùn)行時(shí)才被載入,因?yàn)樵诔绦蜻\(yùn)行期間還需要?jiǎng)討B(tài)庫的存在沪悲。

    靜態(tài)庫 好處

    1. 模塊化获洲,分工合作,提高了代碼的復(fù)用及核心技術(shù)的保密程度
    2. 避免少量改動(dòng)經(jīng)常導(dǎo)致大量的重復(fù)編譯連接
    3. 也可以重用殿如,注意不是共享使用

    動(dòng)態(tài)庫 好處:

    1. 使用動(dòng)態(tài)庫贡珊,可以將最終可執(zhí)行文件體積縮小,將整個(gè)應(yīng)用程序分模塊涉馁,團(tuán)隊(duì)合作门岔,進(jìn)行分工,影響比較小

    2. 使用動(dòng)態(tài)庫烤送,多個(gè)應(yīng)用程序共享內(nèi)存中得同一份庫文件寒随,節(jié)省資源

    3. 使用動(dòng)態(tài)庫,可以不重新編譯連接可執(zhí)行程序的前提下帮坚,更新動(dòng)態(tài)庫文件達(dá)到更新應(yīng)用程序的目的妻往。

    4. 應(yīng)用插件化

    5. 軟件版本實(shí)時(shí)模塊升級

    6. 在其它大部分平臺(tái)上,動(dòng)態(tài)庫都可以用于不同應(yīng)用間共享试和, 共享可執(zhí)行文件讯泣,這就大大節(jié)省了內(nèi)存。
      iOS平臺(tái) 在 iOS8 之前阅悍,蘋果不允許第三方框架使用動(dòng)態(tài)方式加載好渠,從 iOS8 開始允許開發(fā)者有條件地創(chuàng)建和使用動(dòng)態(tài)框架,這種框架叫做 Cocoa Touch Framework节视。雖然同樣是動(dòng)態(tài)框架拳锚,但是和系統(tǒng) framework 不同,app 中使用 Cocoa Touch Framework 制作的動(dòng)態(tài)庫 在打包和提交 app 時(shí)會(huì)被放到 app main bundle 的根目錄 中寻行,運(yùn)行在沙盒里晌畅,而不是系統(tǒng)中。也就是說寡痰,不同的 app 就算使用了同樣的 framework,但還是會(huì)有多份的框架被分別簽名棋凳,打包和加載拦坠。不過 iOS8 上開放了 App Extension 功能,可以為一個(gè)應(yīng)用創(chuàng)建插件剩岳,這樣主app和插件之間共享動(dòng)態(tài)庫還是可行的贞滨。
      蘋果系統(tǒng)專屬的framework 是共享的(如UIKit), 但是我們自己使用 Cocoa Touch Framework 制作的動(dòng)態(tài)庫是放到 app bundle 中,運(yùn)行在沙盒中的

靜態(tài)庫和動(dòng)態(tài)庫的存在的形式

  • 靜態(tài)庫:以.a 和 .framework為文件后綴名。

  • 動(dòng)態(tài)庫:以.tbd(之前叫.dylib) 和 .framework 為文件后綴名晓铆。(系統(tǒng)直接提供給我們的framework都是動(dòng)態(tài)庫I琢肌)

    理解.a 是一個(gè)純二進(jìn)制文件.framework 中除了有二進(jìn)制文件之外還有資源文件骄噪。 .a 尚困,要有 .h 文件以及資源文件配合, .framework 文件可以直接使用链蕊∈绿穑總的來說,.a + .h + sourceFile = .framework滔韵。所以創(chuàng)建靜態(tài)庫最好還是用.framework的形式

靜態(tài)庫和動(dòng)態(tài)庫的區(qū)別

 不同點(diǎn)

  • 靜態(tài)庫在鏈接時(shí)逻谦,會(huì)被完整的復(fù)制到可執(zhí)行文件中,如果多個(gè)App都使用了同一個(gè)靜態(tài)庫陪蜻,那么每個(gè)App都會(huì)拷貝一份邦马,缺點(diǎn)是浪費(fèi)內(nèi)存。類似于定義一個(gè)基本變量宴卖,使用該基本變量是是新復(fù)制了一份數(shù)據(jù)滋将,而不是原來定義的;

  • 動(dòng)態(tài)庫不會(huì)復(fù)制嘱腥,只有一份耕渴,程序運(yùn)行時(shí)動(dòng)態(tài)加載到內(nèi)存中,系統(tǒng)只會(huì)加載一次齿兔,多個(gè)程序共用一份橱脸,節(jié)約了內(nèi)存。類似于使用變量的內(nèi)存地址一樣分苇,使用的是同一個(gè)變量添诉;

    共同點(diǎn):

  • 靜態(tài)庫和動(dòng)態(tài)庫都是閉源庫,只能拿來滿足某個(gè)功能的使用医寿,不會(huì)暴露內(nèi)部具體的代碼信息

靜態(tài)庫的處理方式

  • 對于一個(gè)靜態(tài)庫而言栏赴,其實(shí)已經(jīng)是編譯好的了,類似一個(gè) .o 的集合 這里并沒有連接谬以。在 build 的過程中只會(huì)參與鏈接的過程盯串,而這個(gè)鏈接的過程簡單的講就是合并寺旺,并且鏈接器只會(huì)將靜態(tài)庫中被使用的部分合并到可執(zhí)行文件中去森篷。相比較于動(dòng)態(tài)庫斗蒋,靜態(tài)庫的處理起來要簡單的多篮幢,具體如下圖:

    image.png
  • 鏈接器會(huì)將所有.o用到的 global symbol 和 unresolved symbol 放入一個(gè)臨時(shí)表卖哎,而且是 global symbol 是不能重復(fù)的筐骇。

  • 對于靜態(tài)庫的 .o , 連接器會(huì)將沒有任何 symbol 在 unresolved symbol table 的給忽略惠拭。

  • unresolved symbol 類似 extern int test(); --- **.h **的 聲明?

  • global symbol 類似 void test() { print("test")} -- .m 的 實(shí)現(xiàn)?

  • 最后扩劝,鏈接器會(huì)用函數(shù)的實(shí)際地址來代替函數(shù)引用。

動(dòng)態(tài)庫的處理方式

  • 首先,對于動(dòng)態(tài)庫而言其實(shí)分 動(dòng)態(tài)鏈接庫 和 動(dòng)態(tài)加載庫 兩種的棒呛,這兩個(gè)最本質(zhì)的區(qū)別還是加載時(shí)間聂示。
    • 動(dòng)態(tài)鏈接庫:在沒有被加載到內(nèi)存的前提下,當(dāng)可執(zhí)行文件被加載簇秒,動(dòng)態(tài)庫也隨著被加載到內(nèi)存中鱼喉。在 Linked Framework and Libraries 設(shè)置的一些 share libraries≡姿【隨著程序啟動(dòng)而啟動(dòng)】
    • 動(dòng)態(tài)加載庫:當(dāng)需要的時(shí)候再使用 dlopen 等通過代碼或者命令的方式來加載蒲凶。【在程序啟動(dòng)之后】
  • 但是不論是哪種動(dòng)態(tài)庫拆内,相比較與靜態(tài)庫旋圆,動(dòng)態(tài)庫處理起來要棘手的多。由于動(dòng)態(tài)庫是動(dòng)態(tài)的麸恍,所以你事先不知道某個(gè)函數(shù)的具體地址灵巧。因此動(dòng)態(tài)鏈接器在鏈接函數(shù)的時(shí)候需要做大量的工作。

因?yàn)閯?dòng)態(tài)庫在鏈接函數(shù)需要做大量的工作抹沪,而靜態(tài)庫已經(jīng)實(shí)現(xiàn)處理好了刻肄。所以單純的在所有都沒有加載的情況下,靜態(tài)庫的加載速度會(huì)更快一點(diǎn)融欧。而在 iOS 開發(fā)中的『庫』(一) 提到的有所不妥敏弃,正確應(yīng)該是,雖然動(dòng)態(tài)庫更加耗時(shí)噪馏,但是對于在加載過的share libraries不需要再加載的這個(gè)前提下麦到,使用動(dòng)態(tài)庫可以節(jié)省一些啟動(dòng)時(shí)間。

  • 而實(shí)現(xiàn)這個(gè)動(dòng)態(tài)鏈接是使用了 Procedure Linkage Table (PLT)欠肾。首先這個(gè) PLT 列出了程序中每一個(gè)函數(shù)的調(diào)用瓶颠,當(dāng)程序開始運(yùn)行,如果動(dòng)態(tài)庫被加載到內(nèi)存中刺桃,PLT 會(huì)去尋找動(dòng)態(tài)的地址并記錄下來粹淋,如果每個(gè)函數(shù)都被調(diào)用過的話,下一次調(diào)用就可以通過 PLT 直接跳轉(zhuǎn)了瑟慈,但是和靜態(tài)庫還是有點(diǎn)區(qū)別的是桃移,每一個(gè)函數(shù)的調(diào)用還是需要通過一張 PLT。這也正是 sunny 所說的所有靜態(tài)鏈接做的事情都搬到運(yùn)行時(shí)來做了葛碧,會(huì)導(dǎo)致更慢 的原因借杰。

從源代碼到app

當(dāng)我們點(diǎn)擊了 build 之后,做了什么事情呢吹埠?

  • 預(yù)處理(Pre-process):把宏替換,刪除注釋,展開頭文件缘琅,產(chǎn)生 .i 文件粘都。
  • 編譯(Compliling):把之前的 .i 文件轉(zhuǎn)換成匯編語言,產(chǎn)生 .s文件刷袍。
  • 匯編(Asembly):把匯編語言文件轉(zhuǎn)換為機(jī)器碼文件翩隧,產(chǎn)生 .o 文件。
  • 鏈接(Link):對.o文件中的對于其他的庫的引用的地方進(jìn)行引用呻纹,生成最后的可執(zhí)行文件(同時(shí)也包括多個(gè) .o 文件進(jìn)行 link)堆生。

相關(guān)動(dòng)態(tài)庫和靜態(tài)庫的創(chuàng)建

動(dòng)態(tài)庫動(dòng)態(tài)更新問題

能否動(dòng)態(tài)庫的方式來動(dòng)態(tài)更新AppStore上的版本呢?

framework本來是蘋果專屬的內(nèi)部提供的動(dòng)態(tài)庫文件格式雷酪,但是自從2014年WWDC之后淑仆,開發(fā)者也可以自定義創(chuàng)建framework實(shí)現(xiàn)動(dòng)態(tài)更新(繞過apple store審核,從服務(wù)器發(fā)布更新版本)的功能哥力,這與蘋果限定的上架的app必須經(jīng)過apple store的審核制度是沖突的蔗怠,所以含有自定義的framework的app是無法在商店上架的,但是如果開發(fā)的是企業(yè)內(nèi)部應(yīng)用吩跋,就可以考慮嘗試使用動(dòng)態(tài)更新技術(shù)來將多個(gè)獨(dú)立的app或者功能模塊集成在一個(gè)app上面D洹(我開發(fā)的就是企業(yè)內(nèi)部使用的app,我們將企業(yè)官網(wǎng)中的板塊開發(fā)成4個(gè)獨(dú)立的app锌钮,然后將其改造為framework文件最終集成在一款平臺(tái)級的app當(dāng)中進(jìn)行使用桥温,這樣就可以在一款app上面使用原本4個(gè)app的全部功能!)

**  使用自定義的動(dòng)態(tài)庫的方式來動(dòng)態(tài)更新只能用在 in house(企業(yè)發(fā)布) 和develop 模式卻但不能在使用到 AppStore **因?yàn)樵谏蟼鞔虬臅r(shí)候梁丘,蘋果會(huì)對我們的代碼進(jìn)行一次 Code Singing侵浸,包括 app 可執(zhí)行文件和所有Embedded 的動(dòng)態(tài)庫。因此兰吟,只要你修改了某個(gè)動(dòng)態(tài)庫的代碼通惫,并重新簽名,那么 MD5 的哈希值就會(huì)不一樣混蔼,在加載動(dòng)態(tài)庫的時(shí)候履腋,蘋果會(huì)檢驗(yàn)這個(gè) hash 值,當(dāng)蘋果監(jiān)測到這個(gè)動(dòng)態(tài)庫非法時(shí)惭嚣,就會(huì)造成 Crash

iOS 如何使用 framework 來進(jìn)行動(dòng)態(tài)更新遵湖!

重要參考文檔(一定要看):

  1. iOS 利用 Framework 進(jìn)行動(dòng)態(tài)更新

談?wù)?Mach-O

image
  • 在制作 framework 的時(shí)候需要選擇這個(gè) Mach-O Type.
  • 為Mach Object文件格式的縮寫,它是一種用于可執(zhí)行文件晚吞,目標(biāo)代碼延旧,動(dòng)態(tài)庫,內(nèi)核轉(zhuǎn)儲(chǔ)的文件格式槽地。作為a.out格式的替代迁沫,Mach-O提供了更強(qiáng)的擴(kuò)展性芦瘾,并提升了符號表中信息的訪問速度。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末集畅,一起剝皮案震驚了整個(gè)濱河市近弟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挺智,老刑警劉巖祷愉,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赦颇,居然都是意外死亡二鳄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門媒怯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來订讼,“玉大人,你說我怎么就攤上這事沪摄∏担” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵杨拐,是天一觀的道長祈餐。 經(jīng)常有香客問我,道長哄陶,這世上最難降的妖魔是什么帆阳? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮屋吨,結(jié)果婚禮上蜒谤,老公的妹妹穿的比我還像新娘。我一直安慰自己至扰,他們只是感情好鳍徽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著敢课,像睡著了一般阶祭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上直秆,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天濒募,我揣著相機(jī)與錄音,去河邊找鬼圾结。 笑死瑰剃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的筝野。 我是一名探鬼主播晌姚,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼粤剧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了挥唠?” 一聲冷哼從身側(cè)響起俊扳,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猛遍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體号坡,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡懊烤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宽堆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腌紧。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖畜隶,靈堂內(nèi)的尸體忽然破棺而出壁肋,到底是詐尸還是另有隱情,我是刑警寧澤籽慢,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布浸遗,位于F島的核電站,受9級特大地震影響箱亿,放射性物質(zhì)發(fā)生泄漏跛锌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一届惋、第九天 我趴在偏房一處隱蔽的房頂上張望髓帽。 院中可真熱鬧,春花似錦脑豹、人聲如沸郑藏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽必盖。三九已至,卻和暖如春击碗,著一層夾襖步出監(jiān)牢的瞬間筑悴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工稍途, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阁吝,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓械拍,卻偏偏與公主長得像突勇,于是被迫代替她去往敵國和親装盯。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

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