深刻iOS瞭解靜態庫

簡介程序員

程序員編寫的是源代碼,而計算機運行的則是CPU能識別的機器指令,所以必需要有一系列工具或程序來將源代碼轉化爲機器指令,這個轉化的過程須要經歷編譯和連接兩個主要階段。所謂編譯就是將源代碼文件轉化爲中間的目標文件(Object file)。目標文件的後綴通常爲.o。iOS系統的目標文件也是一種mach-o格式的文件,mach-o文件的頭部結構體:struct mach_header中的filetype成員字段用來描述當前文件的類型,目標文件所對應的類型是MH_OBJECT。目標文件中的佈局結構和內容和可執行文件中的佈局結構和內容很是類似,編譯後造成的目標文件中的代碼段(__TEXT Segment)中的節(__text Section) 中的內容存放的是已經被編譯爲機器指令的二進制代碼了。面試

iOS開發交流技術羣:563513413,無論你是大牛仍是小白都歡迎入駐 ,分享BAT,阿里面試題、面試經驗,討論技術, 你們一塊兒交流學習成長!segmentfault

靜態庫和動態庫的存在形式安全

  • 靜態庫:.a 和 .framework
  • 動態庫:.dylib 和 .framework

靜態庫和動態庫的區別app

  • 靜態庫:連接時,靜態庫會被完整地複製到可執行文件中,被屢次使用就有多份冗餘拷貝
  • 動態庫:連接時不復制,程序運行時由系統動態加載到內存,供程序調用,系統只加載一次,多個程序共用,節省內存
  • 下面就是一個目標文件的佈局結構:

image.png函數

重定位表(Relocation table)工具

系統的編譯操做是針對一個個源文件的獨立行爲。一般狀況下在編寫程序時會引用其餘源文件或者動態庫中定義的函數或者類方法以及全局變量,所以在編譯階段全部的外部引用符號的地址是沒法被肯定的,此時生成的目標文件中的段(Segment)中的節(Section)中的外部函數調用指令的操做數部分以及外部全局變量符號的地址的值都將是0。在後續的連接過程當中須要調整這些指令的操做數的值來進行重定位(Relocation),爲此係統在編譯的目標文件中的對那些有外部符號引用的節(Section)中都會創建一個重定位表(Relocation table)。這個重定位表中的每一個條目會將全部須要進行重定位的指令或者數據訪問的位置信息以及引用的外部符號的信息記錄起來,以便在連接時進行更新處理。下面的圖表展現了這個結構:佈局

image學習

簡要的說一下連接步驟所作的事情ui

當編譯器對全部的源代碼文件編譯完成後,接下來的步驟就是連接了。連接的主要功能就是將全部目標文件中的各個相同段和節的信息依次鏈接起來拼裝成一個單獨的可執行文件。同時還會將全部目標文件中須要Relocation的部分的指令進行調整,由於此時能夠知道每一個引用符號的位置了。在連接時系統會分析每一個目標文件中的依賴信息,也就是說連接成一個可執行文件中各段各節的內容老是無依賴的目標文件放在前面而有依賴的目標文件放置在後面。

靜態庫的做用

每當咱們build一個工程項目時,系統老是會先將全部源代碼編譯爲目標文件,再將目標文件連接爲可執行程序。即便是咱們改變其中某一個文件中的源代碼,而其餘文件沒有改變也是如此。所以爲了加快編譯速度,有些文件將再也不以源代碼的形式提供,而是能夠將一部分目標文件先集中起來造成一個靜態庫。這樣就能夠對這部分文件略過編譯而直接進行連接從而加快編譯的速度。

對於iOS系統來講由於不支持第三方以動態庫的形式集成到咱們的工程中以及上傳到appstore。而第三方提供的庫由於安全和知識產權以及保密的特性不大可能以源代碼的形式提供給咱們,而是以靜態庫的形式提供給咱們。

可見靜態庫的做用主要是爲了加快編譯速度、進行模塊劃分、以及代碼安全的功能。靜態庫是一個編譯產生的結果,而動態庫則是編譯連接產生的結果。靜態庫的組成實際上是一個個目標文件。

相關文章
相關標籤/搜索