現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的**都從零開始。盡量不重複做別人已經做過的事,「站在巨人的肩膀上」做事情。
根據鏈結時期的不同,庫又有:靜態庫和共享庫(動態庫)。
二者的不同點在於**被載入的時刻不同, 靜態庫的**在編譯過程中已經被載入可執行程式,因此體積較大。共享庫的**是在可執行程式執行時才載入記憶體的,在編譯過程中僅簡單的引用,因此**體積較小。
一般gcc在編譯的時候預設使用動態庫,可以直接新增-static強制使用靜態庫。
靜態庫的名字一般是lib***.a(linux).
動態庫的名字一般是lib***.so(linux),有時候也是 lib***.so.major.minor,***x是該lib的名稱,major是主版本號, minor是副版本號。
1 file命令
file程式是用來判斷檔案型別的,並且可以檢視檔案是否使用了動態庫。
where@ubuntu:~$ file /bin/ls/bin/ls: elf 32
-bit lsb executable, intel 80386, version 1 (sysv), dynamically linked (uses shared libs), for gnu/linux 2.6.24, buildid[sha1]=de9c5af34773e23cf554e0da78320e76a3b85120, stripped
2 ldd命令
ldd是英文list dynamic dependencies的縮寫,用來檢視動態庫,如果目標程式沒有鏈結動態庫,則列印「not a dynamic executable」 (不是動態可執行檔案)
where@ubuntu:~$ ldd /bin/lslinux-gate.so.1 => (0xb7765000)
libselinux.so.1 => /lib/i386-linux-gnu/libselinux.so.1 (0xb772a000)
libacl.so.1 => /lib/i386-linux-gnu/libacl.so.1 (0xb7721000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7572000)
libpcre.so.3 => /lib/i386-linux-gnu/libpcre.so.3 (0xb7534000)
libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb752f000)
/lib/ld-linux.so.2 (0x800d3000)
libattr.so.1 => /lib/i386-linux-gnu/libattr.so.1 (0xb7529000)
3 編譯動態庫
#ifndef __mylib_h__#define __mylib_h__
inttest();
#endif
#include#include "mylib.h"
inttest()
gcc -fpic 作用於編譯階段,告訴編譯器產生與位置無關**(position-independent code), 則產生的**中,沒有絕對位址,全部使用相對位址,故而**可以被載入器載入到記憶體的任意 位置,都可以正確的執行。這正是共享庫所要求的,共享庫被載入時,在記憶體的位置不是固定的。-fpic
-c mylib.c
gcc-shared mylib.o -o libmy.so
gcc-shared
-fpic mylib.c -o libmy.so
4 呼叫動態庫
#include "mylib.h"intmain()
gcc-o test test.c libmy.so
gcc-o test test.c -l./ -lmy
exportlibrary_path
=$library_path/homw/where/lib #/home/where為我當前庫路徑
gcc-o test test.c -lmy
mv libmy.so /usr/lib #或者 /lib /usr/local/libgcc-o test test.c -lmy
gcc預設查詢動態的順序:
1、-l引數指定的路徑2、library_path環境變數指明庫搜尋路徑
3、gcc內定庫/lib、/usr/lib、/usr/local/lib
5 標頭檔案引用
gcc test.c -o test -lmy
gcc test.c-o test -i./
exportc_include_path
=$c_include_path:/home/where/lib
gcc test.c -o test
1、當前編譯路徑2、-i 指定的路徑
3、c_include_path,cplus_include_path環境變數等路徑
4、再找系統內定目錄如/usr/include、/usr/local/include
6執行時庫查詢
1、在配置檔案/etc/ld.so.conf中指定動態庫搜尋路徑
sudovi /etc/ld.so.conf.d/mylib.conf #新建mylib.conf寫入你自己的庫路徑,如/home/where/lib
sudo ldconfig
#更新一下快取才能生效
2、通過環境變數ld_library_path指定動態庫搜尋路徑
export3、預設的動態庫搜尋路徑/lib、/usr/libld_library_path
=$ld_library_path:/home/where/lib
7 編譯靜態庫
#ifndef __mylib_h__#define __mylib_h__
inttest();
#endif
#include#include "test.h"
inttest()
gcc-c mylib.c
ar rcs libmy.a mylib.o
引數r:#在庫中插入模組(替換)。當插入的模組名已經在庫中存在,則替換同名的模組。如果若干模組中有乙個模組在庫中不存在,ar顯示乙個錯誤訊息,並不替換其他同名模組。預設的情況下,新的成員增加在庫的結尾處,可以使用其他任選項來改變增加的位置。引數c:#建立乙個庫。不管庫是否存在,都將建立。
引數s:#建立目標檔案索引,這在建立較大的庫時能加快時間。
8 呼叫靜態庫
gcc-o test test.c libmy.a
gcc-o test test.c -l. -lmy
gcc-o test test.c -l. -lmy
-static
Linux靜態庫與動態庫
靜態庫 a 靜態庫的 在編譯過程中已經被載入可執行程式,因此體積較大。編譯程式時候需要庫作依賴,執行時候不需要。方便,不再需要外部函式庫支援 缺點 1 因為靜態庫被鏈結後直接嵌入可執行程式中,相當於每乙個可執行程式裡都有乙個庫的副本,浪費空間 2 一旦庫中有bug,需要重新編譯。建立步驟 1 編寫函...
Linux 靜態庫與動態(共享)庫
不論是在linux還是windows下程式設計,我們都會用到庫,有自身帶的標準庫,也有我們自己寫的庫,庫就是預先編譯好的的方法的集合。linux中的庫可以分為兩種,靜態庫和動態庫,動態庫也稱為共享庫。在linux中,庫名稱都以lib開始,靜態庫名為 lib a,動態庫名為 lib so。靜態庫和動態...
Linux中靜態庫與動態庫
在windows和linux下都存在著大量的庫,庫是什麼呢?本質上來說,庫時一種可執行 的二進位制形式,可以被作業系統載入記憶體執行。我們通常將一些公用函式寫成函式庫,所以庫是別人寫好的,現有的,成熟的,可以服用的 你可以使用但要必須得遵守許可協議。在我們現實開發過程中,不可能每乙份 都從頭編寫,當...