關於鏈接器

編譯器和解釋器執行代碼的特點如下:

  • 採用編譯器生成機器碼執行的好處就是效率高,缺點就是調試時間長
  • 採用解釋器執行的好處是編寫調試方便,缺點是執行效率低

iOS開發採用的編譯器是 LLVM

LLVM是編譯器工具鏈接技術的一個集合。其中 lld 項目是內置鏈接器。編譯器會對每個文件進行編譯,生成Mach-O(可執行文件);鏈接器會將項目中的多個 Mach-O 文件合併成一個

LLVM編譯過程如下:

  • 首先 LLVM會預處理代碼,如把宏嵌入到對應的位置。
  • 預處理完後,LLVM 會對代碼進行詞法分析和語法分析,生成 AST。AST 是抽象語法樹,結構上比代碼更精簡,遍歷起來更快,所以使用AST 能夠更快速地進行靜態檢查。
  • 最後 AST 生成 IR, IR是一種更接近機器碼的語言,區別在於和平臺無關,通過IR 可以生成多份適合不同平臺的機器碼。對於 iOS 系統來說,IR 生成的可執行文件就是 Mach-O.

Mach-O 文件裏的內容,主要是代碼和數據:代碼是函數的定義;數據是全局變量的定義,包括全局變量的初始值。

鏈接器的作用就是完成變量、函數符號和其他地址綁定的任務。

鏈接器會把項目中的多個 Mach-O 文件最終合併成一個,爲什麼呢?自己想想看。

鏈接器在鏈接多個目標文件時,會創建一個符號表,用於記錄所用已定義的和所有未定義的符號。

庫鏈接

靜態庫時編譯時鏈接的庫,需要鏈接到 Mach-O 文件裏,如果需要更新就要重新編譯一次,無法動態加載和更新;而動態庫是運行時鏈接的庫,使用 dyld 就可以實現動態加載。運行時通過 dlopen 和 dlsym 導入動態庫時,先根據記錄的庫路徑找到對應的庫,再通過記錄的名字符號找到綁定的地址。

dyld 加載動態庫有兩種方法:有程序啓動加載時綁定和符號第一次被用到時綁定。爲了減少啓動時間,大部分動態庫使用的都是符號第一次被用到時再綁定的方式。

編譯、鏈接、執行、動態庫加載、 main 函數開始執行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章