linux下動態庫的生成和鏈結

2021-07-11 13:41:11 字數 3742 閱讀 3255

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...