三探·模块拼装思想(静态链接)
程序設(shè)計(jì)的模塊化是程序員一直追求的目標(biāo),因?yàn)楫?dāng)一個(gè)系統(tǒng)非常復(fù)雜的時(shí)候,我們就不得不把一個(gè)復(fù)雜的系統(tǒng)逐步分割成曉得系統(tǒng)以達(dá)到各個(gè)突破的目的。一個(gè)復(fù)雜軟件的開(kāi)發(fā)過(guò)程也如此;首先把每個(gè)源代碼模塊獨(dú)立地編譯,然后按照需要將他們“組裝”起來(lái),這個(gè)組裝過(guò)的過(guò)程就是我們通常說(shuō)的鏈接的過(guò)程。鏈接的主要內(nèi)容就是把各個(gè)模塊之間相互引用的部分處理好,使得各個(gè)模塊之間能夠正確地銜接。
鏈接器所做的工作和程序員“人工調(diào)整地址”本質(zhì)上是一樣的。只不過(guò)現(xiàn)代高級(jí)語(yǔ)言的諸多特性和功能,使得編譯器、鏈接器更為復(fù)雜,功能更為強(qiáng)大。但是從原理上面講,她的工作無(wú)非就是把一些指令對(duì)其他符號(hào)地址的引用加以修正。鏈接過(guò)程主要包括地址和空間分配(Address and Storage Allocation)、符號(hào)決議(Symbol Resolution)和重定位(Relocation)等這些步驟。
1.靜態(tài)鏈接過(guò)程示意圖
每個(gè)模塊的源代碼文件(如.c文件)經(jīng)過(guò)編譯器編譯成目標(biāo)文件(Object File,一般擴(kuò)展名為.o或.obj文件)。目標(biāo)文件與庫(kù)(libarary)一起鏈接形成最終的可執(zhí)行文件。而最常見(jiàn)的庫(kù)就是運(yùn)行時(shí)庫(kù)(Runtime Library)。他是支持程序運(yùn)行的基本函數(shù)集合。庫(kù)其實(shí)是一組目標(biāo)文件的包,就是一些最常用的代碼編輯成目標(biāo)文件后打包存放。 注:對(duì)于object文件沒(méi)有一個(gè)很合適的中文名稱(chēng),我們把它稱(chēng)為中間目標(biāo)文件還是比較合適的,簡(jiǎn)稱(chēng)為目標(biāo)文件。
2.鏈接的內(nèi)部執(zhí)行過(guò)程
現(xiàn)代的鏈接和編譯過(guò)程也并非想想中的那么復(fù)雜,他還是一個(gè)比較容易理解的概念。比如我們?cè)诔绦蚰Kmain.c中使用另外一個(gè)模塊func.c中的函數(shù)foo()。我們?cè)趍ain.c模塊中每一處調(diào)用foo的時(shí)候都必須明確知道foo函數(shù)的地址,所以鏈接器暫時(shí)把這些調(diào)用foo函數(shù)的指令的目標(biāo)地址擱置,等待最后鏈接的時(shí)候由鏈接器區(qū)將這些指令的目標(biāo)地址修正。如果沒(méi)由鏈接器,那么我們就必須手動(dòng)的修改,即填入正確的foo函數(shù)地址。 這里我們需要注意一點(diǎn)的是:當(dāng)func.c模塊被重新編譯,foo函數(shù)的地址有可能改變時(shí),那么我們?cè)趍ain.c中所有使用到的foo地址指令將要全部重新調(diào)整。如果沒(méi)由鏈接器,那么這一項(xiàng)工作對(duì)于程序員來(lái)說(shuō)就是一個(gè)噩夢(mèng)!使用鏈接器,我們可以直接引用其他模塊的函數(shù)和全局變量而不用知道他們的地址!!!(這對(duì)程序員來(lái)說(shuō),無(wú)疑是個(gè)Big Surprise)因?yàn)檫B接器在鏈接的時(shí)候,會(huì)根據(jù)我們程序中所引用的foo符號(hào),自動(dòng)去相應(yīng)的func.c模塊中查找foo地址,然后將main.c模塊中所有引用到foo的指令重新進(jìn)行修改,讓他們的目標(biāo)地址為真正的foo函數(shù)地址。這就是靜態(tài)鏈接的最基本的過(guò)程和作用。與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的三探·模块拼装思想(静态链接)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 二探·编译与连接
- 下一篇: 随便说说程序员团队精神的荣辱与共