【Linux】編譯,鏈接,裝載簡(jiǎn)單梳理

簡(jiǎn)單梳理為了更快的記憶理解及傳達(dá)

一.編譯

1.1 編譯過程:

在這里插入圖片描述

編譯產(chǎn)出文件:


在這里插入圖片描述

1.2 ELF文件類型:

linux中有如下幾種ELF文件:

在這里插入圖片描述

當(dāng)然Android手機(jī)中的oat文件也是ELF文件。

編譯生成的可執(zhí)行文件是ELF文件,ELF文件相關(guān)知識(shí)具體參考:https://blog.csdn.net/TaylorPotter/article/details/90247231

這里簡(jiǎn)單列兩個(gè)視圖:

1.2.1 鏈接視圖:

在這里插入圖片描述

幾個(gè)常見section的作用:
text 段的布局如下:
[.text]:程序代碼
[.rodata]:只讀數(shù)據(jù)
[.hash]:符號(hào)散列表
[.dynsym]:共享目標(biāo)文件符號(hào)數(shù)據(jù)
[.dynstr]:共享目標(biāo)文件符號(hào)名稱
[.plt]:過程鏈接表
[.rel.got]:G.O.T 重定位數(shù)據(jù)。

data 段布局如下:
[.data]:全局的初始化變量
[.dynamic]:動(dòng)態(tài)鏈接結(jié)構(gòu)和對(duì)象
[.got.plt]:全局偏移表
[.bss]:全局未初始化變量

1.2.2 裝載/執(zhí)行視圖:

在這里插入圖片描述

看執(zhí)行視圖最直接感受就是不同section具有一樣的屬性的,比如可讀可寫,會(huì)劃分到相同的segment中去往內(nèi)存中裝載.

二.鏈接

2.1 鏈接過程:

在這里插入圖片描述

1.靜態(tài)鏈接使用靜態(tài)庫,在編譯階段抽取靜態(tài)庫中的依賴的目標(biāo)文件進(jìn)行鏈接,最終可執(zhí)行文件中是包含靜態(tài)庫中依賴的目標(biāo)文件的.
2.動(dòng)態(tài)鏈接使用動(dòng)態(tài)庫,在裝載執(zhí)行時(shí)系統(tǒng)發(fā)現(xiàn)所依賴的動(dòng)態(tài)庫不在物理內(nèi)存中便會(huì)產(chǎn)生缺頁錯(cuò)誤,使用linker去加載動(dòng)態(tài)庫至物理內(nèi)存.當(dāng)然也可以主動(dòng)load 動(dòng)態(tài)庫(dlopen等)

2.2 靜態(tài)鏈接:

在這里插入圖片描述

1.靜態(tài)鏈接將所有需要的目標(biāo)文件鏈接到最終的可執(zhí)行文件中,為了提高程序運(yùn)行裝載效率,將相似section放在一起.

2.3 動(dòng)態(tài)鏈接:

動(dòng)態(tài)鏈接基本思想:把程序按照模塊拆分成各個(gè)相對(duì)獨(dú)立部分,在程序運(yùn)行時(shí)才將它們鏈接在一起形成一個(gè)完整的程序.

假設(shè)現(xiàn)在有兩個(gè)程序program1.o和program2.o,這兩者共用同一個(gè)庫lib.o,假設(shè)首先運(yùn)行程序program1,系統(tǒng)首先加載program1.o,當(dāng)系統(tǒng)發(fā)現(xiàn)program1.o中用到了lib.o,即program1.o依賴于lib.o,那么系統(tǒng)接著加載lib.o,如果program1.o和lib.o還依賴于其他目標(biāo)文件,則依次全部加載到內(nèi)存中。當(dāng)program2運(yùn)行時(shí),同樣的加載program2.o,然后發(fā)現(xiàn)program2.o依賴于lib.o,但是此時(shí)lib.o已經(jīng)存在于內(nèi)存中,這個(gè)時(shí)候就不再進(jìn)行重新加載,而是將內(nèi)存中已經(jīng)存在的lib.o映射到program2的虛擬地址空間中,從而進(jìn)行鏈接(這個(gè)鏈接過程和靜態(tài)鏈接類似)形成可執(zhí)行程序。

在這里插入圖片描述

動(dòng)態(tài)鏈接最關(guān)鍵通過got表中基于got表起始地址的偏移中的地址值確定動(dòng)態(tài)鏈接庫中的函數(shù)實(shí)際地址,日后再詳細(xì)調(diào)研學(xué)習(xí)這塊.

2.4 鏈接類型比較:

在這里插入圖片描述

靜態(tài)鏈接如果program A和 program B都使用到c.o,需要各自鏈接c.o至各自的可執(zhí)行文件中,
缺點(diǎn):比較浪費(fèi)空間,另外更新困難.
優(yōu)點(diǎn): 編譯時(shí)鏈接,啟動(dòng)性能相對(duì)較好.
動(dòng)態(tài)鏈接中不需要重復(fù)裝載已裝載的共享庫,運(yùn)行時(shí)將共享庫的映射到進(jìn)程的虛擬地址空間中即可
優(yōu)點(diǎn): 節(jié)省空間,更新方便
缺點(diǎn): 運(yùn)行時(shí)準(zhǔn)確來說是裝載時(shí)鏈接,影響啟動(dòng)性能

據(jù)估算,動(dòng)態(tài)鏈接與靜態(tài)鏈接相比,性能損失大約在5%以下,這點(diǎn)性能損失用來換取程序在空間上的節(jié)省和程序構(gòu)建和升級(jí)時(shí)的靈活性是相當(dāng)值得的.

三.裝載

3.1 裝載過程:

在這里插入圖片描述

1.裝載過程即可執(zhí)行文件加載到內(nèi)存中開始執(zhí)行的過程,系統(tǒng)會(huì)將可執(zhí)行文件中對(duì)應(yīng)的section依據(jù)上面提到的執(zhí)行視圖映射到虛擬內(nèi)存中,
2.若執(zhí)行到這一段虛擬內(nèi)存時(shí)發(fā)現(xiàn)該虛擬內(nèi)存對(duì)應(yīng)的物理內(nèi)存是空的則會(huì)發(fā)生缺頁中斷,下一步即會(huì)將可執(zhí)行文件的該部分裝載到物理內(nèi)存中,
3.然后執(zhí)行.

3.2 native程序裝載執(zhí)行過程:

在這里插入圖片描述

1.裝載的過程即exec執(zhí)行過程,exec執(zhí)行發(fā)現(xiàn)虛擬地址指向的物理地址沒有代碼或數(shù)據(jù)MMU便會(huì)產(chǎn)生缺頁錯(cuò)誤,去加載該段內(nèi)容到物理內(nèi)存中執(zhí)行.
2.大部分程序都采用動(dòng)態(tài)鏈接,當(dāng)程序從內(nèi)核轉(zhuǎn)到用戶太時(shí)第一次執(zhí)行的并非程序的入口地址,而是linker動(dòng)態(tài)連接器的入口.
3.動(dòng)態(tài)連接器自舉之后會(huì)去鏈接裝載程序需要的動(dòng)態(tài)庫,準(zhǔn)備好了之后才會(huì)去調(diào)用可執(zhí)行程序文件的入口,繼而調(diào)用到程序的main方法.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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