2012年2月6日 星期一

linux底下用C語言建立dynamic library

dynamic library,顧名思義就是動態的,library並不如之前靜態的,在編譯時期就進入code,而是在執行的時候,再由ld.so去連結該library。為了管理與節省時間系統通常會對library做cache,由ldconfig指令來做一些操作,預設是讀取/etc/ld.so.conf裡的路徑做資料cache,可以透過ldconfig -v更新cache

檔案名稱規則是用lib開頭,附加.so,最後放上版本編號

gcc -fPIC -c -Wall display.c
gcc -shared -Wl,-soname,libdisplay.so.1 -o libdisplay.so.1.0.1 display.o

fPIC表示Position Independent Code
W1是W(one數字1)

這裡先釐清幾個事情
libdisplay.so (一般是一個 symbolic link,連到 libdisplay.so.1.0.1)
libdisplay.so.1 ( 一般是一個 symbolic link,連到 libdisplay.so.1.0.1 ) (有人稱它為soname)
libdisplay.so.1.0.1  (有人稱它為real name)
一般來說,soname後面有個版本,相同的版本可以提供相同的介面才是,所以後面真實link到的是1.0.3或者1.0.1就可以忽略
libdisplay.so供連接器ld使用(當你用-l參數時),soname個供dynamic loader使用,最後一個是實際檔案。
一般我們都會將程式庫放在/usr/lib中,但通常我會都會依照GNU Directory VariablesStandard及FHS(Filesystem Hierarchy Standard)來決定程式庫的擺放位置,若根據GNU的標準所說,所有發佈式(非原本系統及系統服務額外所需的)的程式庫都應放在/usr/local/lib,系統管理員亦需加入/usr/local/lib為程式庫連結目錄,只有與系統有關的程式庫才會被放進/usr/lib;而根據FHS的標準而言,非系統服務用的程式庫也可放在/usr/lib之下的目錄裡。請留意GNU的標準與FHS並沒有衝突,因為GNU的標準是以程式庫開發者的角度來想,即是你需要一個外來的程式庫來發展你的程式時,你會把它放在/usr/local/lib;而FHS則是以使用者的角度來想,當你安裝一軟件時所需要的額外程式庫,則你多數會把它放在/usr/lib。在安裝程式庫時,你需把以real name命名的程式庫放在適當的目錄(/usr/lib或/usr/local/lib或其他,以後例子均使用/usr/lib),然後建立兩條分別以soname及linker name命名的symbolic link指向real name程式庫檔案,當然你也可以用ldconfig來協助你建立symbolic及cache,但ldconfig並不會為你建立以linker name命名的symbolic link, 而且自行建立看起來更快捷及可靠。


一般來說是這樣,因為dynamic library的概念就是把大家都用的到的code分享出來,所以必須放到大家都可以取得的地方,以linux來說,他會去搜尋/usr/lib跟/lib,跟/usr/local/lib,所以在編譯的時候連結跟靜態的一致,只要加上-L跟-l參數就可以

ln -sf libdisplay.so.1.0.1 libdisplay.so
gcc test.c -L./ -ldisplay -o test

第一道指令是給linker在編譯程式的時候用的,因為linker會去尋找libdisplay.so或者libdisplay.a,並不管版本號碼。
雖然編譯會過關,但是他並不能執行,主要是因為libdisplay.so.1.0.1並沒有放在預設的目錄下。執行時候ld.so會動態嘗試到預設的目錄下去找library,這時候就會找不到,發生執行的錯誤。一開始大家都會有個環境變數LD_LIBRARY_PATH,藉由更新他可以使用一個非正規的方式達到效果
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
這樣再去執行./test就可以了

參考資料:
http://blog.mchz.com.cn/?p=4590
http://www.yunsec.net/a/special/linux/application/2010/0606/4322_2.html
http://www.vr.ncue.edu.tw/esa/EmbeddedSystemProgramming2010/ch09.htm
http://blog.ykyi.net/2011/12/linux%E7%9A%84soname%EF%BC%8C%E9%93%BE%E6%8E%A5%E5%BA%93%E7%9A%84%E9%97%AE%E9%A2%98/
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html

沒有留言:

張貼留言