2010-07-01 22 views
5

我對這個網站的第一篇文章與巨大的希望:: 我想了解靜態鏈接,動態鏈接,共享庫,靜態庫等與海灣合作委員會。每次我試圖深入研究這個話題時,我都有一些我不太明白的東西。在海灣合作委員會如何在運行時強制符號解析

一些實踐工作:

bash$ cat main.c 

#include "printhello.h" 
#include "printbye.h" 

void main() 
{ 
PrintHello(); 
PrintBye(); 
} 

bash$ cat printhello.h 
void PrintHello(); 

bash$ cat printbye.h 
void PrintBye(); 

bash$ cat printbye.c 
#include <stdio.h> 

void PrintBye() 
{ 
printf("Bye bye\n"); 
} 

bash$ cat printhello.c 
#include <stdio.h> 

void PrintHello() 
{ 
printf("Hello World\n"); 
} 

gcc -Wall -fPIC -c *.c -I. 
gcc -shared -Wl,-soname,libcgreet.so.1 -o libcgreet.so.1.0 *.o 
ln -sf libcgreet.so.1.0 libcgreet.so 
ln -sf libcgreet.so.1.0 libcgreet.so.1 

所以我創建了一個共享庫。 現在我想鏈接這個共享庫與我的主程序來創建一個可執行文件。

gcc -Wall -L. main.c -lcgreet -o greet

它很好的工作,如果我跑迎接(或rpath的選項鍊接的話)之前設置LD_LIBRARY_PATH我可以使它發揮作用。

然而,我的問題是不同的: 因爲我無論如何都使用共享庫,是不是可以在運行時強制進行符號解析(根據本書「鏈接器和加載器」不知道術語,也許稱爲動態鏈接) 。我明白我們可能不想這樣做,因爲這會讓程序運行緩慢,每次我們想運行該程序都會產生開銷,但我正試圖理解這一點以清除我的概念。

gcc鏈接器是否提供任何選項來延遲運行時的符號解析? (要與我們實際上要運行該程序的庫一起使用)(因爲在編譯時可用的庫可能與運行時可用的庫不同(如果庫中有任何更改) 我希望能夠做某事:

bash $ gcc main.c -I。

(在這裏需要什麼選項?) 這樣我就不必提供庫名稱,只是告訴它我想在運行時進行符號解析,所以頭文件對於現在來說足夠好,實際的庫名稱不需要。

謝謝, 永遠的學習者。

+0

http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html – adf88 2010-07-01 13:07:39

+0

請確保您使用適當的語言標記問題。它被標記爲C++,但代碼是C.請注意,爲了能夠使用純動態庫加載C++中的代碼,需要包含額外的'extern「C」',它們不需要,也不需要在C中有效。 – 2010-07-01 15:28:33

回答

9

任何鏈接器(gcc,ld或任何其他)只在編譯時解析鏈接。這是因爲ELF標準(與大多數其他標準一樣)沒有按照您所描述的定義「運行時」鏈接。它們要麼靜態鏈接(即lib.a),要麼在啓動時鏈接(lib.so,在加載ELF時必須存在)。但是,如果您使用動態鏈接,則鏈接程序將只將ELF文件的名稱和它必須找到的符號放入ELF中,而不直接鏈接文件。因此,如果您想稍後將lib升級到新版本,只要系統可以找到相同的文件名(路徑實際上可能不同)和相同的符號名稱,就可以這樣做。

在運行時獲得符號的另一種選擇是使用dlopen,它與gccld無關。 dlopen簡單地說,打開一個動態鏈接庫,就像fopen可能,並返回一個句柄,然後你將它傳遞到dlsym與你想要的符號的名稱,可能是一個函數名稱例如。然後dlsym將向您傳遞一個指向該符號的指針,然後您可以使用該指針調用該函數或將其用作變量。這就是插件的實現方式。

+0

+1爲好的答案,並指出插件。 – stinky472 2010-07-01 13:22:18

+1

如果C++語言標記是正確的,請記住將這些符號標記爲'extern「C」',以便它們在編譯時不會被破壞。 – 2010-07-01 15:30:06

1

我認爲你正在尋找ld選項'--unresolved-symbols = ignore-all',是的,它實際上可以做到這一點(忽略prev答案)。想象一下,在共享庫加載較晚(程序已經運行時)的情況下,它可以使用已經由主進程解析/加載的所有符號,無需再費心去做。順便說一句,它並不神經使其緩慢,至少在Linux上

相關問題