靜態鏈結 空間的位址和分配

2021-10-07 20:27:49 字數 1465 閱讀 6040

參考文獻

對於鏈結器來說,在連線過程中。它的工作就是把多個輸入的目標檔案加工成合併成乙個輸出檔案。這一篇部落格就是介紹的靜態鏈結中空間與位址分配的,有關靜態鏈結的其他內容以及動態鏈結的資訊我會在之後的部落格介紹。

按序疊加可以說是最簡單的乙個方案,就是將輸入的目標檔案按照次序疊加起來。

但是從圖中我們可以看到,在有很多輸入檔案的情況下,輸出檔案將有很多零散的段。因為每個段都要遵循空間對齊,所以這樣無疑會占用大量空間。

比如,乙個段長度只有1位元組,但是按照空間對齊,其在記憶體也要占用4096個位元組。
為了解決按需疊加所帶來的問題,引入了相似段合併這個概念。顧名思義,就是把相同性質的段合併到一起。

就像我在部落格:目標檔案詳解中提到的,.bss段其實在目標檔案和可執行檔案中 並不占用檔案的空間(即不占用磁碟空間),但是在裝載時是要占用位址空間的。

很多書中提到的「鏈結器為目標檔案分配位址和空間」,這一句話其實是有兩個含義的。對於.text和.data這樣有實際資料的段,鏈結器在檔案中和虛擬位址中都要分配空間。但是對於.bss這樣的段,在檔案中就不必分配空間,目的是節約磁碟空間

目前的鏈結器都不採用按序疊加的方法,而是採用相似段合併的方法。

剛剛我們說,鏈結器採用的是相似段合併的方法,使用這種方法的鏈結器一般都採用兩步鏈結的方法。

第一步 空間與位址分配:鏈結器獲取所有目標檔案的段長度,並且將他們合併,計算出輸出檔案中各個段合併後的長度與位置,建立對映關係。

第二步 符號解析與重定位:使用上一步所收集到的資訊,讀取輸入檔案中段的資料、重定位資訊、進行符號解析和重定位、調解**中的位址。符號詳解

鏈結器前後的程式所用的位址其實已經是程式應該在程序中使用的虛擬位址。linux下一般衝0x08048000開始分配。至於為什麼會從這個地方開始分配,我將在接下來的部落格逐步介紹。

乙個程式在載入到記憶體中一般會有4g的虛擬位址空間,其中1g是核心空間,3g程序空間。
符號位址的確定

位址確定很簡單就,基址位址(0x08048000)+偏移位址(符號在程序中的位址)。

[1] 俞甲子 石凡 潘愛明.程式設計師的自我修養.電子工業出版社,2009.4.

Linux c 靜態鏈結的空間和位址分配

a.c include extern intshared int main b.c int shared 1 void swap int a,int b 操作 gcc c a.c b.c 生成a.o b.o 操作 ld a.o b.o e main o ab e main 使用ld鏈結器,將main...

windows 位址空間分配

當系統建立乙個程序同時為其建立它位址空間時,此位址空間中大部分都是閒置的。為了使用這部分位址空間,我們必須呼叫virtualalloc來分配其中的區域。分配區域的操作被稱為預定。當應用程式預定位址空間區域時,系統會確保預定的區域的起始位址正好是分配粒度的整數倍。分配粒度根據不同的平台而有所不同。現在...

空間與位址分配

我們知道,可執行檔案中的 段和資料段都是由輸入的目標檔案中合併而來的。那麼鏈結器是如何將它們的各個段合併到輸出檔案?或者說,輸出檔案中的空間如何分配給輸入檔案的。最簡單的方案就是直接將各個目標檔案依次合併,但是這樣做輸出檔案將會有很多零散的段。這種做法非常浪費空間,因為每個段都需要有一定的位址和空間...