Linux下動態庫文件的文件名形如 libxxx.so
,其中so是 Shared Object 的縮寫,即可以共享的目標文件。
在鏈接動態庫生成可執行文件時,並不會把動態庫的代碼復制到執行文件中,而是在執行文件中記錄對動態庫的引用。
程序執行時,再去加載動態庫文件。如果動態庫已經加載,則不必重復加載,從而能節省內存空間。
Linux下生成和使用動態庫的步驟如下:
- 編寫源文件。
- 將一個或幾個源文件編譯鏈接,生成共享庫。
- 通過
-L<path> -lxxx
的gcc選項鏈接生成的libxxx.so。 - 把libxxx.so放入鏈接庫的標准路徑,或指定
LD_LIBRARY_PATH
,才能運行鏈接了libxxx.so的程序。
下面通過實例詳細講解。
編寫源文件
建立一個源文件: max.c,代碼如下:
int max(int n1, int n2, int n3) { int max_num = n1; max_num = max_num < n2? n2: max_num; max_num = max_num < n3? n3: max_num; return max_num; }
編譯生成共享庫:
gcc -fPIC -shared -o libmax.so max.c
我們會得到libmax.so。
實際上上述過程分為編譯和鏈接兩步, -fPIC是編譯選項,PIC是 Position Independent Code 的縮寫,表示要生成位置無關的代碼,這是動態庫需要的特性; -shared是鏈接選項,告訴gcc生成動態庫而不是可執行文件。
上述的一行命令等同於:
gcc -c -fPIC max.c gcc -shared -o libmax.so max.o
為動態庫編寫接口文件
為了讓用戶知道我們的動態庫中有哪些接口可用,我們需要編寫對應的頭文件。
建立 max.h ,輸入以下代碼:
#ifndef __MAX_H__ #define __MAX_H__ int max(int n1, int n2, int n3); #endif
測試,鏈接動態庫生成可執行文件
建立一個使用max
函數的test.c,代碼如下:
#include <stdio.h> #include "max.h" int main(int argc, char *argv[]) { int a = 10, b = -2, c = 100; printf("max among 10, -2 and 100 is %d.\n", max(a, b, c)); return 0; }
gcc test.c -L. -lmax
生成a.out,其中-lmax
表示要鏈接libmax.so
。-L.
表示搜索要鏈接的庫文件時包含當前路徑。
注意,如果同一目錄下同時存在同名的動態庫和靜態庫,比如 libmax.so
和 libmax.a
都在當前路徑下,
則gcc會優先鏈接動態庫。
運行
運行 ./a.out
會得到以下的錯誤提示。
./a.out: error while loading shared libraries: libmax.so: cannot open shared object file: No such file or directory
找不到libmax.so,原來Linux是通過 /etc/ld.so.cache
文件搜尋要鏈接的動態庫的。
而 /etc/ld.so.cache
是 ldconfig 程序讀取 /etc/ld.so.conf
文件生成的。
(注意, /etc/ld.so.conf
中並不必包含 /lib
和 /usr/lib
,ldconfig
程序會自動搜索這兩個目錄)
如果我們把 libmax.so
所在的路徑添加到 /etc/ld.so.conf
中,再以root權限運行 ldconfig
程序,更新 /etc/ld.so.cache
,a.out
運行時,就可以找到 libmax.so
。
但作為一個簡單的測試例子,讓我們改動系統的東西,似乎不太合適。
還有另一種簡單的方法,就是為a.out
指定 LD_LIBRARY_PATH
。
LD_LIBRARY_PATH=. ./a.out
程序就能正常運行了。LD_LIBRARY_PATH=.
是告訴 a.out
,先在當前路徑尋找鏈接的動態庫。
對於elf格式的可執行程序,是由ld-linux.so*來完成的,它先后搜索elf文件的
DT_RPATH
段, 環境變量LD_LIBRARY_PATH
, /etc/ld.so.cache文件列表, /lib/,/usr/lib目錄, 找到庫文件后將其載入內存. (http://blog.chinaunix.net/uid-23592843-id-223539.html)
makefile讓工作自動化
編寫makefile,內容如下:
.PHONY: build test clean build: libmax.so libmax.so: max.o gcc -o $@ -shared $< max.o: max.c gcc -c -fPIC $< test: a.out a.out: test.c libmax.so gcc test.c -L. -lmax LD_LIBRARY_PATH=. ./a.out clean: rm -f *.o *.so a.out
make build
就會生成libmax.so
, make test
就會生成a.out
並執行,make clean
會清理編譯和測試結果。