iOS高手開發(fā)課讀書筆記:符號是怎么綁定到地址上的

說句實(shí)話,作為一個開發(fā),平時每天在寫代碼,但是對于代碼的編譯過程并不是十分的了解,最近看了戴老師的鏈接器這篇文章,大概有了一些了解,做個筆記。

項(xiàng)目開發(fā)完成,我們需要進(jìn)行編譯來看修改后的效果,但是假如編譯的是一些大型的項(xiàng)目,那么恐怕編譯時間將非常的長,因此就需要對此進(jìn)行一些優(yōu)化,要優(yōu)化必須先了解一下啟動時鏈接器所做的事情。簡單來說,鏈接器做的最重要的事情就是把符號綁定在地址上。

在說鏈接器之前,先來看看iOS所使用的編譯器,在iOS開發(fā)中,我們所寫的代碼會被編譯器轉(zhuǎn)化為機(jī)器碼,然后CPU會直接執(zhí)行機(jī)器碼,除去編譯器,還有一種叫做解釋器,但是蘋果并沒有使用,因?yàn)樘O果希望程序執(zhí)行的效率更高,速度更快。

為什么說解釋器的速度慢,效率不高呢?因?yàn)?code>解釋器是在運(yùn)行時將我們寫的代碼,一句句的翻譯成目標(biāo)代碼,然后再一句句的執(zhí)行目標(biāo)代碼,這個效率肯定就是不如事先生成一份完整的機(jī)器碼再去執(zhí)行。

那么為什么解釋器效率低還有人會用呢?學(xué)iOS的人一定會對運(yùn)行時比較敏感,解釋器是在運(yùn)行時期間發(fā)生作用的,那么使用解釋器就可以隨時增加或者更新代碼來改變項(xiàng)目內(nèi)容,無需重啟項(xiàng)目就可以看到代碼更新的結(jié)果,而且如果項(xiàng)目上線出現(xiàn)問題,也可以隨時更新,用戶無需更新即可升級使用。這就大大縮短了程序開發(fā)周期和功能更新周期。

好了現(xiàn)在弄清楚了蘋果使用編譯器的原因,我們就來看看蘋果使用的是什么編譯器,相信大家和我一樣,總看到LLVM,也知道它是蘋果的編譯器,但是對它了解的并不是很多,在Xcode5之前,蘋果的編譯器使用的是GCC,后來換成了LLVM,它的速度要比GCC高出三倍之多。

LLVM是編譯器工具鏈技術(shù)的一個集合,而其中的lld就是內(nèi)置鏈接器。編譯器會對每個文件進(jìn)行編譯,生成Mach-O(可執(zhí)行文件),鏈接器將會把生成的Mach-O合并成為一個。

LLVM的工作簡單來說可概括為幾點(diǎn):

1.咱們寫好的代碼,LLVM會預(yù)處理一下,比如把我們定義的宏嵌入到相應(yīng)的位置。
2.預(yù)處理完成之后,LLVM會對代碼進(jìn)行詞法分析語法分析,生成ASTAST就是抽象語法樹,結(jié)構(gòu)上比代碼更精簡,可以更快速的遍歷,可以更快的生成IR(中間表示)。
3.最后AST會生成IR,IR是一種更接近機(jī)器碼的語言,通過IR可生成多份適合不同平臺的機(jī)器碼,對于iOS系統(tǒng)來說,生成的就是Mach-O。

那么鏈接器做了什么呢?通俗點(diǎn)說,Mach-O里面的主要內(nèi)容就是我們的代碼和數(shù)據(jù),代碼就是我們所寫的函數(shù),也就是各種方法,數(shù)據(jù)就是我們定義的全局變量,無論是方法,還是各種全局變量,它們的實(shí)例都需要和方法名稱,變量名稱聯(lián)系起來。當(dāng)我們的系統(tǒng)想要操作各種方法,各種變量時,必然需要找到方法名稱,變量名稱所對應(yīng)的地址,而鏈接器所做的工作就是將方法,變量名稱所對應(yīng)的地址關(guān)聯(lián)起來。

那么鏈接器為什么還要把生成的多個Mach-O合并成為一個呢?我們平時寫代碼肯定是不會把所有的內(nèi)容都寫在一個文件里面,一個項(xiàng)目一般會包含很多文件,而各個文件之間的方法接口,數(shù)據(jù)都是相互依賴的,因此單個文件生成的Mach-O是肯定無法正常運(yùn)行的,如果這個文件調(diào)用了其他文件中的方法,那么就無法找到這個方法的地址,也就無法執(zhí)行。

鏈接器在鏈接多個目標(biāo)文件的時候會創(chuàng)建一個符號表,記錄所有已經(jīng)定義,和未定義的符號,我們在編譯項(xiàng)目的時候經(jīng)常會遇到這個錯誤“l(fā)d: dumplicate symbols”,這就說明項(xiàng)目里面有重復(fù)的文件,也會遇到這個錯誤“Undefined symbols”這就說明項(xiàng)目中缺少文件。

鏈接器還有一個作用,就是會自動去除長時間沒有使用的函數(shù),使其不會被打包進(jìn)入Mach-O文件,如果我們項(xiàng)目迭代的過程中,廢棄了一些函數(shù),不再調(diào)用,久而久之,被廢棄的函數(shù)越來越多,我們的Mach-O會變得越來越大。鏈接器在整理函數(shù)符號調(diào)用關(guān)系時就會自動去除掉廢棄的函數(shù)。鏈接器在整理函數(shù)符號調(diào)用關(guān)系時,會以main函數(shù)為源頭,跟隨每個引用,被跟蹤到的會標(biāo)記為live,未被標(biāo)記的就是無用函數(shù),鏈接器就會自動去除無用函數(shù)。

以上就是這一章的部分筆記,最后還是推薦大家去看原文,大家共同進(jìn)步!

原文地址:https://time.geekbang.org/column/article/86840

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容