linux靜態鏈結庫與動態鏈結庫詳解

2021-08-27 15:51:38 字數 4130 閱讀 2798

一順便說說了哦

通常情況下,對函式庫的鏈結是放在編譯時期(compile time)完成的.所有相關的物件檔案(object file)與牽涉到的函式庫(library)被鏈結合成乙個可執行檔案(executable file).程式在執行時,與函式庫再無瓜葛,因為所有需要的函式已拷貝到自己門下。所以這些函式庫被成為靜態庫(static libaray),通常檔名為"lib***.a"的形式.

其實,我們也可以把對一些庫函式的鏈結載入推遲到程式執行的時期(runtime).這就是如雷貫耳的動態鏈結庫(dynamic link library)技術.

二動態鏈結庫的特點與優勢

首先讓我們來看一下,把庫函式推遲到程式執行時期載入的好處:

1.可以實現程序之間的資源共享。

什麼概念呢?就是說,某個程式的在執行中要呼叫某個動態鏈結庫函式的時候,作業系統首先會檢視所有正在執行的程式,看在記憶體裡是否已有此庫函式的拷貝了。如果有,則讓其共享那乙個拷貝;只有沒有才鏈結載入。這樣的模式雖然會帶來一些「動態鏈結」額外的開銷,卻大大的節省了系統的記憶體資源。c的標準庫就是動態鏈結庫,也就是說系統中所有執行的程式共享著同乙個c標準庫的**段.

2.將一些程式公升級變得簡單。使用者只需要公升級動態鏈結庫,而無需重新編譯鏈結其他原有的**就可以完成整個程式的公升級。windows 就是乙個很好的例子。

3.甚至可以真正坐到鏈結載入完全由程式設計師在程式**中控制。

程式設計師在編寫程式的時候,可以明確的指明什麼時候或者什麼情況下,鏈結載入哪個動態鏈結庫函式。你可以有乙個相當大的軟體,但每次執行的時候,由於不同的操作需求,只有一小部分程式被載入記憶體。所有的函式本著「有需求才調入」的原則,於是大大節省了系統資源。比如現在的軟體通常都能開啟若干種不同型別的檔案,這些讀寫操作通常都用動態鏈結庫來實現。在一次執行當中,一般只有一種型別的檔案將會被開啟。所以直到程式知道檔案的型別以後再載入相應的讀寫函式,而不是一開始就將所有的讀寫函式都載入,然後才發覺在整個程式中根本沒有用到它們。

三、靜態動態鏈結庫的建立

由於動態鏈結庫函式的共享特性,它們不會被拷貝到可執行檔案中。在編譯的時候,編譯器只會做一些函式名之類的檢查。在程式執行的時候,被呼叫的動態鏈結庫函式被安置在記憶體的某個地方,所有呼叫它的程式將指向這個**段。因此,這些**必須實用相對位址,而不是絕對位址。在編譯的時候,我們需要告訴編譯器,這些物件檔案是用來做動態鏈結庫的,所以要用位址不無關**(position independent code (pic)).

原始碼如下:

zj@zj:~/c_pram/practice$ cat fun.c

#include

void mylib1()

void mylib2()

zj@zj:~/c_pram/practice$ cat call.c

main()

靜態鏈結庫建立:

zj@zj:~/c_pram/practice$ gcc -c fun.c

zj@zj:~/c_pram/practice$ ar cqs libfun.a fun.o

zj@zj:~/c_pram/practice$ gcc call.c -static -l. -lfun -o fun_static_call

zj@zj:~/c_pram/practice$ ./fun_static_call

library1 routine called

library2 routine called

動態鏈結庫建立:

/*生成動態鏈結庫*/

zj@zj:~/c_pram/practice$ gcc fun.c -fpic -shared -o libfun.so

/*-l指定查詢動態鏈結庫的路徑,-lfun實際就是查詢libfun.so*/

zj@zj:~/c_pram/practice$ gcc call.c -l. -lfun -o fun_dyn_call

/*未指定環境變數ld_library_path*/

zj@zj:~/c_pram/practice$ ./fun_dyn_call

./fun_dyn_call: error while loading shared libraries: libfun.so: cannot open shared object file: no such file or directory

zj@zj:~/c_pram/practice$ export ld_library_path=$ld_library_path:~/c_pram/practice

zj@zj:~/c_pram/practice$ ./fun_dyn_call

library1 routine called

library2 routine called

static,表示建立靜態鏈結庫,shared 標籤告訴編譯器這是要建立動態鏈結庫。這與靜態鏈結庫的建立很不一樣,後者用的是 ar 命令。也注意到,靜態鏈結庫的名字形式為 "lib***.a" 字尾名為 ".a",動態鏈結庫的名字形式為 "lib***.so" 字尾名為 ".so"

使用動態鏈結庫,首先需要在編譯期間讓編譯器檢查一些語法與定義。

這與靜態庫的實用基本一樣,用的是 -lpath 和 -l*** 標籤。如:

gcc call.c -l. -lfun -o fun_dyn_call

四、ld_library_path環境變數的設定

在程式執行期間,也需要告訴系統去**找你的動態鏈結庫檔案。在unix下是通過定義名為 ld_library_path 的環境變數來實現的。只需將path賦值給此變數即可。

為了讓執行程式順利找到動態庫,有三種方法:

(1)把庫拷貝到/usr/lib和/lib目錄下。

(2)在ld_library_path環境變數中加上庫所在路徑。例如動態庫libhello.so在/home/ting /lib目錄下,以bash為例,使用命令:

$export ld_library_path=$ld_library_path:~/c_pram/practice

在環境變數ld_library_path後新增~/c_pram/practice

(3) 修改/etc/ld.so.conf檔案,把庫所在的路徑加到檔案末尾,並執行sudo ldconfig重新整理(需要超級使用者許可權)。這樣,加入的目錄下的所有庫檔案都可見.

ubuntu下:

zj@zj:~/c_pram/practice$ cat /etc/ld.so.conf

include /etc/ld.so.conf.d/*.conf

zj@zj:~/c_pram/practice$ ls /etc/ld.so.conf.d/

i486-linux-gnu.conflibc.conf

original:

zj@zj:~/c_pram/practice$ cat /etc/ld.so.conf.d/libc.conf

# libc default configuration

/usr/local/lib

after:

zj@zj:~/c_pram/practice$ cat /etc/ld.so.conf.d/libc.conf

# libc default configuration

/usr/local/lib

/home/zj/c_pram/practice

當然由於ld.so.conf包含/etc/ld.so.conf.d/*.conf,你也可以自己新建個檔案vi /etc/ld.so.conf.d/myownlib.conf,然後在其中輸入/home/zj/c_pram/practice.這種方法實現的reboot後應該也可以,我還沒有reboot重啟後告訴大家阿,或者你可以告訴我.

五.檢視庫中的符號

一切安排妥當後,再使用ldd命令檢視可執行檔案依賴於哪些庫,針對動態哦

zj@zj:~/c_pram/practice$ ldd fun_static_call

not a dynamic executable

zj@zj:~/c_pram/practice$ ldd fun_dyn_call

linux-gate.so.1 =>(0xb7f06000)

libfun.so => /home/zj/c_pram/practice/libfun.so (0xb7f02000)

libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7da1000)

/lib/ld-linux.so.2 (0xb7f07000)

動態鏈結庫與靜態鏈結庫

有人會想,動態鏈結這樣麻煩,為什麼還要用呢?這裡有乙個技術問題,對這個問題的解決直接導致了動態載入的需求。問題是有些dll只在某個windows版本中存在,或某個api只在某些windows版本中被加入指定的dll。當你使用靜態鏈結的.exe試圖在不支援的windows版本上執行時,系統會彈出系統對...

動態鏈結庫與靜態鏈結庫

原貼出處 http blog.csdn.net benny5609 archive 2008 04 17 2298998.aspxs 還有參考 http msdn.microsoft.com zh cn library 1ez7dh12 v vs.100 aspxs 首先通過乙個簡單的靜態鏈結庫的例...

靜態鏈結 庫 與動態鏈結 庫

靜態鏈結與動態鏈結 簡單的說,靜態庫和應用程式編譯在一起,在任何情況下都能執行,而動態庫是動態鏈結,顧名思義就是在應用程式啟動的時候才會鏈結,所以,當使用者的系統上沒有該動態庫時,應用程式就會執行失敗。再看它們的特點 動態庫 1.共享 多個應用程式可以使用同乙個動態庫,啟動多個應用程式的時候,只需要...