什麼是鏈接
鏈接是將各種代碼和數據片段收集並組合成爲單一文件的過程
編譯器驅動程序
int sum(int *a,int n);
int array[2]={1,2};
int main(){
int val=sum(array,2);
return val;
}
main.c
int sum(int *a,int n){
int i,s=0;
for(i=0;i<n;i++){
s+=a[i];
}
return s;
}
sum.c
我們可以通過下面的語句來調用gcc驅動程序
$ gcc -Og -o prog main.c sum.c
??這裏我不知道怎麼用-v 來查看步驟
我們可以來看一下這個過程(那main.c來說)
首先:
預處理器(cpp)將main.c翻譯成一個ascII碼的中間文件main.i:
cpp [other arguments] main.c /tmp/main.i
接下來,驅動程序運行c編譯器(cc1)將main.i->main.s(ascll彙編語言文件)
cc1 /tmp/main.i -Og[other arguments ] -o /tmp/main.s
然後運行彙編器(as)將main.s轉爲main.o(可重定位目標文件)
as [other argument ] -o /tmp/main.o /tmp/main.s
最後運行連接器(ld),將main.o和sum.o和有關代碼組合起來,形成一個可執行目標文件
ld -o prog [system object files and args] /tmp/main.o /tmp/sum.o
鏈接的主要任務
符號解析
將符號定義與引用對應起來
比如想上面的main.o和sum.o鏈接的過程中,鏈接器就得將main.o中對sum的引用與sum.o中的sum的定義對應起來。
這裏的符號可以是一個函數,一個全局變量,一個靜態變量
思考:這裏爲什麼沒有提到局部變量
重定位
因爲我們的鏈接器和彙編器生成的是從0字節開始的代碼段,鏈接器首先對把每一個符號定義與一個具體的內存位置關聯起來,從而重定位這些節,然後修改所有對這些符號的引用,使他們指向這個內存位置,
目標文件
可重定位目標文件
包含二進制代碼和數據,其形式可以在編譯時與其他可重定位目標文件合併起來
可執行目標文件
包含二進制,代碼和數據,其形式可以被直接複製到內存並執行
共享目標文件:
一種特殊類型的可重定位目標文件,可以在加載或者運行時被動態加載進內存並鏈接