linux下動態庫的生成和鏈結(.so)
本質上來說庫是一種可執行**的二進位制形式,可以被作業系統載入記憶體執行。
windows和linux下都存在庫,但不同。
靜態庫:.a 檔案。靜態庫在程式編譯時會被連線到目標**中,程式執行時將不再需要該靜態庫。
動態庫:.so,也叫共享庫(shared object)。程式執行時的動態鏈結,多個程序可以鏈結同乙個共享庫。動態庫在程式編譯時並不會被連線到目標**中,程式執行時被載入,因此在程式執行時還需要動態庫存在。
優點:一旦動態庫中的函式發生變化,對於可執行程式來說是透明的,可執行程式無需重新編譯。這對於程式的發布、維護、更新起到了積極的作用。
當靜態庫和動態庫同名時, gcc命令將優先使用動態庫
以後慢慢研究原理,先實現乙個最簡單的庫鏈結。
linux下 so檔案即為動態庫,類似於windows下的dll。
作用:1、**復用,簡化**,節約資源
2、不同的應用程式如果呼叫相同的庫,那麼在記憶體裡只需要有乙份該共享庫的例項
#include int a();
int b();
#include "test.h"
int a()
int b()
#include "test.h"
int main()
編譯生成 libtest .so 檔案,並通過鏈結庫編譯生成可執行檔案 mm
gcc test.c -fpic -shared -o libtest.so
gcc main.c -l. -ltest -o mm
-shared:該選項指定生成動態連線庫(讓聯結器生成t型別的匯出符號表,有時候也生成弱連線w型別的匯出符號),不用該標誌外部程式無法連線。相當於乙個可執行檔案
-l.:表示要連線的庫在當前目錄中
-ltest:編譯器查詢動態連線庫時有隱含的命名規則,即在給出的名字前面加上lib,後面加上.so來確定庫的名稱
ld_library_path:這個環境變數指示動態聯結器可以裝載動態庫的路徑。
當然如果有root許可權的話,可以修改/etc/ld.so.conf檔案,然後呼叫 /sbin/ldconfig來達到同樣的目的,不過如果沒有root許可權,那麼只能採用輸出ld_library_path的方法了。
執行:./mm
./mm: error while loading shared libraries: libtest.so: cannot open shared object file: no such file or directory
執行出錯了,原因是作業系統無法找到庫。
檢視一下依賴的庫:ldd mm
ldd mm
linux-vdso.so.1 => (0x00007fffc01ff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f0592b06000)
/lib64/ld-linux-x86-64.so.2 (0x00007f05930af000)
發現libtest.so並沒有鏈結進去
解決方法一:
1、將.so檔案放入預設搜尋路徑中。一般在:/etc/lib/.下
2、在多使用者環境下,一般我們不享有預設路徑寫入的許可權。可以通過設定 ld_library_path 環境變數解決:
export ld_library_path=.
或者: export ld_library_path=$(pwd)
這裡的意思是將當前檔案新增為共享目錄。當然,後面的目錄可以自己手動輸入絕對路徑
缺點:修改環境變數,會影響所有的可執行程式。如果我們在編譯其他程式時,如果我們不小心,很可能導致其他可執行檔案無法執行。
解決方法二:提供 -rpath選項(runtime path)
將搜尋路徑資訊寫入可執行檔案,不需要設定環境變數。
缺點:當庫檔案移動時,需要重新編譯生成可執行檔案。
編譯命令:
gcc -g -o mm main.c -ltest -l. -wl,-rpath=.
-wl(大寫的w,小寫的l)
-rpath選項是傳遞給聯結器(linker),「.」表示當前目錄
ldd mm
linux-vdso.so.1 => (0x00007fffc01ff000)
libtest.so => /opt/code/xqf/dcs/src/linux_practice/libtest.so (0x00007f0592eac000)
libc.so.6 => /lib64/libc.so.6 (0x00007f0592b06000)
/lib64/ld-linux-x86-64.so.2 (0x00007f05930af000)
執行:./mm
hello world
welcome to china
program excute success
成功!!
檔案列表:ll
-rwxr-xr-x 1 root root 1936 apr 20 08:31 libtest.a
-rwxr-xr-x 1 root root 8200 apr 18 22:21 libxqf.so
-rwxr-xr-x 1 root root 105 apr 18 22:19 main.c
-rwxr-xr-x 1 root root 136 apr 18 22:19 test.c
-rwxr-xr-x 1 root root 38 apr 18 19:41 test.h
-rwxr-xr-x 1 root root 1792 apr 19 19:30 test.o
-rwxr-xr-x 1 root root 12410 apr 18 22:24 mm
./mm & 表示在後台執行該可執行檔案
幾點知識,
參考資料:
1. ld會去找gcc命令中的引數-l
2. 再找gcc的環境變數library_path
3. 再找內定目錄 /lib /usr/lib /usr/local/lib 這是當初compile gcc時寫在程式內的
動態鏈結時、執行時搜尋路徑順序:
1. 編譯目標**時指定的動態庫搜尋路徑;
2. 環境變數ld_library_path指定的動態庫搜尋路徑;
3. 配置檔案/etc/ld.so.conf中指定的動態庫搜尋路徑;
4. 預設的動態庫搜尋路徑/lib, /usr/lib, /usr/local/lib
新安裝乙個庫之後如何讓系統能夠找到它
如果安裝在/lib或者/usr/lib下,那麼ld預設能夠找到,無需其他操作。
如果安裝在其他目錄,需要將其新增到/etc/ld.so.cache檔案中,步驟如下
2.執行ldconfig,該命令會重建/etc/ld.so.cache檔案
編譯生成靜態庫:
gcc -c test.c 生成 test.o 檔案
ar crv libtest.a test.o 建立靜態庫檔案 libtest.a
gcc -o mm main.c -static -l. -ltest 生成可執行檔案 mm
執行:./mm
hello world
welcome to china
program excute success
linux下靜態和動態鏈結庫的生成
靜態鏈結庫 1 先將.c檔案編譯成.o檔案 例 gcc c add.c 2 用ar命令生成靜態庫 例 ar rc libadd.a add.o 3 注意 靜態庫命令規則為 lib 名字.a 4 注意使用該靜態檔案時,在編譯時,要通過 i和 l指定對應的標頭檔案和庫檔案的路徑 動態鏈結庫 1 使用命令...
Linux下動態庫的生成及鏈結方法
最近在看 c專家程式設計 看到第5章 對鏈結的思考,正好作為參考,對linux下動態庫的生成及鏈結方法作一下總結。linux下動態庫檔案的擴充套件名為 so shared object 按照約定,所有動態庫檔名的形式是libname.so 可能在名字中加入版本號 這樣,執行緒函式庫被稱作libthr...
linux生成動態鏈結庫
步驟 1 建立動態鏈結庫 建立caculate.c caculate.h兩個檔案 編譯生成libcac.so檔案 gcc shared fpic caculate.c o libcac.so 2 建立測試程式 建立 main.pc檔案 編譯生成可執行檔案 gcc main.c o main l lc...