計算機操作系統——鏈接

Table of Contents

 

編譯系統

靜態鏈接

目標文件

動態鏈接


編譯系統

如下所示的C程序:

#include <stdio.h>

int main()
{
    printf("hello, world\n");
    return 0;
}

 在Unix系統上,由編譯器把源文件轉換爲目標文件。

gcc -o hello hello.c

 這個過程大致如下:

  •  預處理階段:處理以#開頭的預處理文件;
  • 編譯階段:翻譯成彙編文件;
  • 彙編階段:將彙編文件翻譯成可重定位目標文件;
  • 鏈接階段:將可重定位目標文件和printf.o等單獨編譯好的目標文件進行合併,得到最終的可執行目標文件

靜態鏈接

靜態鏈接器以一組可重定位目標文件爲輸入,生成一個完全鏈接的可執行目標文件作爲輸出。鏈接器主要完成以下兩個任務:

  • 符號解析:每個符號對應於一個函數、一個全局變量或一個靜態變量,符號解析的目的是將每個符號引用與一個符號定義關聯起來。
  • 重定位:鏈接器通過把每個符號定義與一個內存位置關聯起來,然後修改所有對這些符號的引用,使得它們指向這個內存位置。

目標文件

  • 可執行目標文件:可以直接在內存中執行;
  • 可重定位目標文件:可與其它可重定位目標文件在鏈接階段合併,創建一個可執行目標文件;
  • 共享目標文件:這是一種特殊的可重定位目標文件,可以在運行時被動態加載進內存並連接。

動態鏈接

靜態庫有如下兩個問題:

  • 當靜態庫更新時那麼整個程序都要重新進行鏈接;
  • 對於printf這種標準函數庫,如果每個程序都要有代碼,這回極大浪費資源。

共享庫是爲了解決靜態庫的這兩個問題而設計的,在Linux系統中通常用.so後綴來表示,Windows系統上它們被稱爲DLL。它具有以下特點:

  • 在給定的文件系統中一個庫只有一個文件,所有引用該庫的可執行目標文件都共享這個文件,它不會複製到引用它的可執行文件中;
  • 在內存中,一個共享庫的.text節(已編譯程序的機器代碼)的一個副本可以被不同的正在運行的進程共享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章