連接器負責的工做:ios
地址綁定、重定位、庫查詢、代碼分段函數
加載器負責的工做:blog
重定位(先因爲硬件重定位而省略)內存
地址綁定:字符串
將更抽象的名字與更底層的名字綁定(如getline名字綁定到iosys模塊內可執行代碼的612字節處,或這個模塊靜態數據開始的第405字節處)。get
重定位:編譯器
編譯器和彙編器生成的目標代碼地址從0開始。一個程序有多個子程序組成,子程序們的地址不能重疊。重定位就是爲程序不一樣部分分配加載地址,調整程序中的數據和代碼以反映所分配地址的過程。數學
重定位通常不止一次,連接時,各子程序經過重定位在大程序中肯定位置。當程序加載時,系統會選擇一個加載地址,而連接好的程序會做爲總體被重定位到加載地址。io
符號解析:編譯
當多個子程序構建一個大程序時,子程序間互相做用是經過符號進行的,如主程序調用sqrt,sqrt定義在數學庫中。連接器經過標明分配給sqrt的地址來解析這個符號,並修改目標代碼使得call指令引用該地址。
程序加載:
將程序從輔助存儲器拷貝到內存中,準備運行。有些狀況下,還包括分配存儲空間,設置保護位,或經過虛擬內存將虛擬地址映射到磁盤內存頁上。
當容許一個程序的多個實例時,程序中的某些部分在全部的容許實例中都是相同的(尤爲時可執行代碼),而另外一些部分是各實例獨有的。
編譯連接實例
m.c
m包含程序段16B,數據段16B(字符串)
符號表:_main(導出符號)、_a(導入符號)
程序先將字符串的地址壓棧,用於傳參。
在調用a函數時,因爲a未知,因此用0x0代替地址,並作好標記。
a.c
a.c程序段0x1c字節
其中調用的庫函數都是未知的因此用0x0代替入口地址
使用靜態連接
連接後數據段變多,是因爲使用靜態連接庫函數
程序增長了啓動代碼start-c,和調用的庫函數例程
_c和_main符號都從新進行地址綁定。
能夠看出靜態連接會複製導入的符號相關的實例,這就形成了程序體積會很大