歡迎您光臨本站 註冊首頁

Linux鏈接庫簡介

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0
Linux鏈接庫簡介 最近要考linux編程,發現linux庫這個東西,怎麼也無法理解,在網上兜了一大圈,看了很多東西,才算模模糊糊搞懂了,下面把自己總結的東西貼上來與大家共享: 在linux系統中,可將多個目標文件打包成庫文件,以便在編程時隨時調用,而不必重新編寫或定義,這種包稱為庫函數.庫文件是一些預先編譯好的函數的集合,那些函數都是按照可再使用的原則編寫的.它們通常由一組互相關聯的用來完成某項常見工作的函數構成.比如用來處理屏幕顯示情況的函數(curses庫)等.
1.基礎知識:
linux下GCC在編譯程序時要經歷預處理,編譯,彙編和連接四個階段.
預處理階段,主要處理#include和#define,它把#include包含進來的.h 文件插入到#include所在的位置,生成.i文件;
編譯階段,是最重要的階段,在這個階段GCC首先檢查語法然後把文件轉換成彙編程序,生成.s文件;上面這兩步的輸出文件都是文本文件,我們可以用諸如cat的文本處理等命令閱讀這些輸出文件;
彙編階段,把*.s文件翻譯成二進位機器指令文件*.o,需要反彙編工具如GDB的幫助才能讀懂它;
連接階段,gcc在這個階段把所有的*.o文件連接成一個可執行文件,庫文件的連接也在這步完成.
2. 標準庫與非標準庫
庫函數可分為標準與非標準(自定義)庫兩大類.
(1)標準庫文件是公用的,系統中的任何用戶都可以利用這些庫函數,一般保存在/lib或者/usr/lib目錄里,並以頭文件的方式提供包含調用.編譯時要告訴C語言編譯器(更確切地說是鏈接程序)應去查找哪些庫文件,默認情況下,它只會查找標準庫文件.


標準庫在使用時,gcc等編譯程序能夠自動連接,在只需要包含其定義的頭文件即可,如libc.a.libc.a為標準C函數庫,它包含了諸如內存管理或者輸入輸出操作的基本函數.
(2)非標準庫在連接時,必須加上-lname(name為去掉lib和尾部的.a或.so后的庫名)參數;非標準庫可以放在任意目錄中,一般放於當前目錄中,但當放置在非系統默認搜索路徑中時,需要用-Ldir(dir為路徑名稱)指定搜索路徑.
例如,數學函數並不是C標準庫的組成部分,他們是由數學庫/usr/lib/libm.a所定義的,因而在使用該庫中的數學函數時,除了用#include<math.h>將頭文件/usr/include/math.h加入到程序文件中,還要明確的用gcc的-lm選項來連接這個庫(數學庫libm.a放置在系統默認的庫搜索路徑/usr/lib中,因而不需要-Ldir參數).
3. 靜態庫與共享庫
函數庫一般分為靜態和共享(也稱動態庫)兩種格式,庫文件必須遵守一定的命名規則,庫文件的名字永遠以lib打頭,隨後是說明函數庫情況的部分(比如用c表示這是一個 C語言庫,而m表示這是一個數學運算庫等).文件名的部分以一個句點(.)開始,然後給出這個庫文件的類型,.a為靜態庫文件,.so和.sa為共享型庫文件.無論動態庫還是靜態庫都需要用.o文件來生成.
一般 Linux 系統把 /lib 和 /usr/lib 兩個目錄作為默認的庫(動態庫或靜態庫)搜索路徑,使用這兩個目錄中的庫時不需要進行設置搜索路徑即可直接使用.對於處於默認庫搜索路徑之外的庫,需要將庫的位置添加到庫的搜索路徑之中(如修改環境變數),也可以在程序連接時,通過-L參數來指定.
但由於在運行時,程序還需要連接動態庫,因而,對於動態庫,最好還是將庫的位置添加到庫的搜索路徑之中或是把所用的庫拷貝到系統默認的庫搜索目錄中.靜態庫則無此限制.


(1)靜態庫
靜態庫也叫做檔案(archive),文件名按慣例都以.a結尾,比如C語言標準庫/usr/lib/libc.a,X11庫/usr/X11R6/lib/libX11.a等.它所包含的成員是若干.o文件,靜態庫中的各個成員(.o文件)沒有特殊的存在格式,僅僅是一個.o文件的集合.在連接時,靜態庫的文件代碼會被拷貝到可執行文件中,靜態連接的可執行文件一般比較大一些.
在Linux(Unix)中使用工具「ar」對靜態庫進行維護管理,創建靜態庫用ar命令,在系統提示符下鍵入以下命令將創建靜態庫文件libmyhello.a.
# ar -rc libmyhello.a hello.o
靜態庫的缺點是,如果我們在同一時間運行多個程序而它們又都使用著來自同一個函數庫里的函數時,內存里就會有許多份同一函數的備份,在程序文件本身也有許多份同樣的備份.這會消耗大量寶貴的內存和硬碟空間.
(2)共享庫
也稱動態庫,許多UNIX系統支持共享庫,它同時克服了靜態庫在內存和硬碟方面的無謂消耗.鏈接時,動態庫的代碼不會被加入可執行文件中,而是在程序被執行的時候載入.
共享庫的默認存放位置和靜態庫是一樣的,但有著不同的文件後綴.在一個典型的 Linux系統上,C語言標準庫的共享版本是/usr/lib/libc.so N,其中的N是主版本號.當靜態庫和動態庫同名時,gcc命令將優先使用動態庫.
可用gcc來創建動態庫,在系統提示符下鍵入以下命令得到動態庫文件libmyhello.so.
# gcc -shared -fPCI -o libmyhello.so hello.o
4. 對比
靜態庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態庫.動態庫在程序編譯時並不會被連接到目標代碼中,而是在程序運行時才被載入,因此在程序運行時還需要動態庫存在.


假如程式是在編譯時載入庫文檔的,就是使用了靜態庫.假如是在運行時載入目標代碼,就成為動態庫.換句話說,假如是使用靜態庫,則靜態庫代碼在編譯時就拷貝到了程式的代碼段,程式的體積會膨脹.假如使用動態庫,則程式中只保留庫文檔的名字和函數名,在運行時去查找庫文檔和函數體,程式的體積基本變化不大.
靜態庫的原則是「以空間換時間」,增加程式體積,減少運行時間;動態庫則是「以時間換空間」,增加了運行時間,但減少了程式本身的體積.
5. 總結
標準靜態庫或共享庫,路徑和庫名都不需顯示指定;
非標準靜態庫,必須顯示指定庫名,不在默認路徑中時需指定路徑;
非標準共享庫,編譯時:必須指定庫名,不在默認路徑中需指定路徑名,
運行時,不在默認路徑中時需要將庫位置添加到庫搜索路徑中或拷貝庫到默認路徑中.
6. gcc相關命令
使用要點:
⑴在gcc 的-I參數后加上庫頭文件的路徑;
⑵在gcc 的-L參數后加上庫文件所在目錄;
⑶在gcc 的-l參數后加上庫文件名,但是要去掉lib和.a擴展名,比如庫文件名是libtest.a 那麼參數就是-ltest.


[火星人 ] Linux鏈接庫簡介已經有303次圍觀

http://coctec.com/docs/linux/show-post-50364.html