Linux下lib編程詳解

來源:互聯網
上載者:User

一、lib類型:
與windows下靜態庫(.lib)和動態庫(.dll)一樣,linux同樣存在靜態庫(static library 檔案尾碼為.a)和共用庫(shared library 檔案尾碼為.so),在/usr/lib目錄下同時存在一個庫的靜態版本和動態版本。

"An archive (or static library) is simply a collection of object files stored as a single file.When you provide an archive to the linker, the linker searches the archive for the object files it needs, extracts them, and links them into your program much as if you had provided thoseobject files directly."

"A shared library is similar to a archive in that it is a grouping of object files. However, there are many important differences.The most fundamental difference is that when a shared library islinked into a program, the final executable does not actually contain the code that ispresent in the shared library. Instead, the executable merely contains a reference to theshared library."

"the object files that compose the shared library are combined into asingle object file so that a program that links against a shared library always includes allof the code in the library, rather than just those portions that are needed."

以上引自《Advanced Linux Programming》

由此可知,靜態庫和共用庫都是一個obj檔案的集合,但靜態連結後,執行程式中存在自己所需obj的一份拷貝,而動態連結後,執行程式僅僅是包含對共用庫的一個引用。共用庫相當於一個由多個obj檔案組合而成的obj檔案,在連結後其所有代碼被載入,不管需要的還是不需要的。

似乎可以得出一個結論:
靜態連結後的程式比動態連結的所用儲存空間大,因為執行程式中包含了庫中代碼拷貝;而動態連結的程式比靜態連結的所用的Runspace大,因為它將不需要的代碼也載入到Runspace。
二、lib編譯:
靜態庫的編譯,實際上是一個將.o檔案打包的過程。

ar -rc libfunc.a func1.o func2.o # 將f1.o、f2.o編譯成靜態庫libfunc.a

動態庫的編譯,使用gcc -fPIC -shared編譯選項。

gcc -fPIC -shared -o libfunc.so func1.o func2.o # 將f1.o、f2.o編譯成動態庫libfunc.so
三、lib調用:
靜態庫的調用比較簡單,跟標準庫函數調用一樣

一個例子:main.c調用./lib目錄下libfunc.a庫,該庫標頭檔在./inc目錄下,編譯:

gcc -o test main.c -I./inc -L./lib -lfunc

共用庫的調用需要注意庫檔案置放位置,如果該庫檔案不在/lib、/usr/lib下,則需要設定LD_LIBRARY_PATH變數。一個例子:main.c調用./lib目錄下libfunc.so庫,該庫標頭檔在./inc目錄下,如果使用編譯:

gcc -o test main.c -I./inc -L./lib -lfunc
./test # 運行錯誤:error while loading shared libraries: libfunc.so

這是因為動態連結時程式只是存放共用庫的名稱而不是絕對路徑,所以運行時我們需要先設定該庫所處位置:

export LD_LIBRARY_PATH=./lib
./test # 運行成功

動態裝載共用庫:在只有共用庫而沒有庫的標頭檔,或者你想在運行時動態載入、卸載庫時,linux的dl庫函數:dlopen、dlclose、dlsym幫你辦到,其相當於windows下LoadLibrary、FreeLibrary、GetProcAddress函數

函數原型:

void *dlopen(const char *filename, int flag);
void *dlsym(void *handle, char *symbol);
int dlclose(void *handle);

一個例子:main.c動態裝載./lib目錄下libfunc.so庫,庫中有一個函數void print_str(const char*);

/*載入庫*/
void *handle = dlopen("libfunc.so", RTLD_LAZY);
/*獲得函數的入口*/
void (*pt_str)(const char*);
pt_str = dlsym(handle, "print_str");
/*調用函數*/
pt_str("hello world.");
/*卸載庫*/
dlclose(handle);

四、相關說明:
1、共用庫特別適合多個程式共用代碼,升級程式部分功能模組,實現程式“外掛程式”功能的情況;而靜態庫是一勞永逸,編譯後不需要帶一堂庫檔案跑,而且不管放置到哪裡都可正常運行。

2、當搜尋的庫檔案目錄下同時存在該庫的靜態版本和共用版本時,連結器優先使用共用版本.so,此時你可以使用-static連結選項指定連結靜態版本.a。

3、動態庫可以匯出兩個特殊的函數:_init和_fini,前者在動態庫被載入後調用,後者在動態庫被卸載前調用,我們可以使用這兩個函數做些特別的工作。需要注意的是:在定義這兩個函數後編譯時間,需要使用-nostartfiles選項,否則編譯器報重複定義錯誤。

4、ldd命令用來查看程式所依賴的共用庫,同時也方便我們判斷共用ẓ是否被找到;nm命令查看obj檔案(.so也是一個obj)中的標識(函數、變數)。

     Linux好學堂, www.linuxhao.com,是學習Linux應用開發綜合性技術網站,類目包括Linux安裝指南,Linux系統管理,Linux網路應用,Linux伺服器技術,Linux編程開發,Linux下載中心,並提供Linux視頻教程,Linux培訓教程,Linux技術資料免費下載與資源共用等服務。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.