c# - linux link static library




“靜態鏈接”和“動態鏈接”是什麼意思? (4)

(我不知道C#,但有一個VM語言的靜態鏈接概念很有趣)

動態鏈接涉及知道如何找到所需的功能,只有您的程序參考。 您的語言運行時或操作系統搜索文件系統,網絡或編譯代碼緩存中的一段代碼,與引用匹配,然後採取多種措施將其集成到內存中的程序映像中,例如重定位。 它們都是在運行時完成的。 它可以手動完成,也可以通過編譯器完成。 有能力更新與混亂的風險(即DLL地獄)。

靜態鏈接在編譯時完成,您可以告訴編譯器所有功能部件在哪裡,並指示它將它們集成在一起。 沒有搜索,沒有歧義,沒有重新編譯就無法更新。 您的所有依賴關係與您的程序映像完全相同。

我經常聽到“靜態鏈接”和“動態鏈接”這兩個術語,通常涉及用CC++C#編寫的代碼,但我對這兩個術語都不太了解。 他們是什麼,他們到底在說什麼,他們鏈接的是什麼?


因為以上所有帖子都沒有顯示如何靜態鏈接某些內容,並且看到您做得正確,因此我將解決此問題:

一個簡單的C程序

#include <stdio.h>

int main(void)
{
    printf("This is a string\n");
    return 0;
}

動態鏈接C程序

gcc simpleprog.c -o simpleprog

並在二進製file上運行:

file simpleprog 

這將顯示它是動態鏈接的:

“對於GNU / Linux 2.6.26,BuildID [sha1] = 0xf715572611a8b04f686809d90d1c0d75c6028f0f,未剝離的”simpleprog:ELF 64位LSB可執行文件,x86-64,版本1(SYSV),動態鏈接(使用共享庫)“

相反,讓我們這次靜態鏈接程序:

gcc simpleprog.c -static -o simpleprog

在這個靜態鏈接的二進製文件上運行文件將顯示:

file simpleprog 

“simpleprog:GNU / Linux 2.6.26,BuildID [sha1] = 0x8c0b12250801c5a7c7434647b7dc65a644d6132b,靜態鏈接的ELF 64位LSB可執行文件,x86-64,版本1(GNU / Linux)

你可以看到它愉快地靜態鏈接。 可悲的是,並非所有的庫都以這種方式進行靜態鏈接很簡單,並且可能需要使用libtool進行擴展,或者手工鏈接目標代碼和C庫。

幸運的是,像musl這樣的許多嵌入式C庫為幾乎全部( 如果不是全部 )庫提供了靜態鏈接選項。

現在對您創建的二進製文件進行處理,您可以看到程序開始前沒有任何庫被訪問:

strace ./simpleprog

現在比較動態鏈接程序中strace的輸出,你會發現靜態鏈接版本的strace要短得多!


我認為這個問題的一個很好的答案應該解釋什麼是鏈接。

當你編譯一些C代碼時(例如),它被翻譯成機器語言。 只是一串字節,運行時會導致處理器添加,減去,比較,“轉到”,讀取內存,寫入內存等等。 這些東西存儲在對象(.o)文件中。

現在,很久以前,計算機科學家發明了這個“子程序”的東西。 執行 - 這 - 塊-的代碼和回報 - 在這裡。 不久之後,他們意識到最有用的子程序可以存儲在一個特殊的地方,並被任何需要它們的程序使用。

現在在早期,程序員必須打入這些子程序所在的內存地址。 類似於CALL 0x5A62 。 如果這些內存地址需要改變,這是乏味且有問題的。

所以,這個過程是自動的。 你編寫一個調用printf()的程序,編譯器不知道printf的內存地址。 因此,編譯器只是寫CALL 0x0000 ,並向對象文件添加一條註釋,說“必須用printf的內存位置替換此0x0000”。

靜態鏈接意味著鏈接器程序(GNU one被稱為ld )將printf的機器代碼直接添加到您的可執行文件,並將0x0000更改為printf的地址。 這發生在您的可執行文件被創建時。

動態鏈接意味著上述步驟不會發生。 可執行文件仍然有一個註釋說“必須用printf的內存位置替換0x000”。 操作系統的加載程序需要找到printf代碼,將其加載到內存中,並在每次運行程序時更正CALL地址。

程序調用一些靜態鏈接的printf是很常見的(像printf這樣的標準庫函數通常是靜態鏈接的)和其他動態鏈接的函數。 靜態的“成為可執行文件的一部分”,動態文件在可執行文件運行時“加入”。

這兩種方法都有優點和缺點,並且操作系統之間存在差異。 但既然你沒有問,我會在這裡結束。


靜態鏈接的庫在編譯時鏈接在一起。 動態鏈接庫在運行時加載。 靜態鏈接將庫位打包到可執行文件中。 動態鏈接僅引用庫中的引用; 動態庫的位存在於其他位置,並可以稍後換出。





dynamic-linking