在程序中總會用到各式各樣的庫,有兩種使用方式:靜態鏈接庫和動態鏈接庫,在windows下分別對應.lib文件和.dll文件,使用靜態庫時需要包含對應的頭文件並引用lib文件,使用動態庫則需要手動通過函數加載dll中的函數。
linux下使用方法則有所不同,linux下.a文件.so文件分別對應靜態和動態鏈接庫。
靜態鏈接庫
ar rcs libmylib.a mylib.o 生成.a靜態庫
gcc -o hello main.c -L. -lmylib 生成可執行文件hello;gcc會在mylib之前自動添加lib,即找文件libmylib.a
./hello 執行
可以發現即使刪除libmylib.a文件,hello也可以執行。
動態鏈接庫
gcc -fPIC -shared -o libmylib.so mylib.c 生成.so動態庫
gcc -o hello main.c -L. -lmylib 生成可執行文件hello;gcc會在mylib之前自動添加lib,即找文件libmylib.so
./hello 執行
./hello: error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory
可以發現此時hello執行出錯,gcc編譯時優先鏈接動態庫文件,但程序執行時並沒有找到動態鏈接庫。
在linux下程序搜索動態鏈接庫是按照如下順序的:
- ELF可執行文件中動態段中DT_RPATH所指定的路徑,編譯時gcc加入鏈接參數“-Wl,-rpath”指定該動態庫搜索路徑
- 環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑
- 配置文檔/etc/ld.so.conf中指定的動態庫搜索路徑
- 默認的動態庫搜索路徑/lib
- 默認的動態庫搜索路徑/usr/lib
按照第一種方法解決,
gcc -o hello main.c -L. -lmylib -Wl,-rpath=. 參數-Wl,-rpath=. 指定當前路徑爲動態庫搜索路徑
./hello 可執行
按照第二種方法解決,
export LD_LIBRARY_PATH=.
./hello 可執行
使用命令 readelf -d hello可見其搜索路徑 Library rpath: [.]
Dynamic section at offset 0x7b0 contains 22 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libmyhello.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [.]
0x000000000000000c (INIT) 0x400490
0x000000000000000d (FINI) 0x4006b8
0x000000006ffffef5 (GNU_HASH) 0x400260
第三種方法,
把當前路徑寫入/etc/ld.so.conf,並執行ldconfig重新加載
第四種方法,
把libmylib.so文件拷貝到/lib中
第四種方法,
把libmylib.so文件拷貝到/lib中
第五種方法,
把libmylib.so文件拷貝到/usr/lib中
在實際使用中第一和第二種方法最經常被採納,但是使用變量LD_LIBRARY_PATH時要注意,一旦LD_LIBRARY_PATH變量被設置之後,該變量生效範圍內的所有程序執行時都會先查找該變量所指定的搜索目錄,這樣勢必會造成一些浪費。
參考http://www.eefocus.com/book/09-04/716171276059628.html
http://blog.chinaunix.net/uid-23592843-id-223539.html