2011年3月15日 星期二

[Linux] gcc自製library

引用: PTT看板: LinuxDev (作者: cole945)

Library可分成三種,static、shared與dynamically loaded, 下面會介紹如何利用 gcc 製作 這三種 library 與引用.

Static libraries :Static 程式庫用於靜態連結,簡單講是把一堆object檔用ar(archiver)包裝集合起來,檔名以 `.a' 結尾。優點是執行效能通常會比後兩者快,而且因為是靜態連結,所以不易發生執行時找不到library或版本錯置而無法執行的問題。缺點則是檔案較大,維護度較低;例如library如果發現bug需要更新,那麼就必須重新連結執行檔.

* 編譯編譯方式很簡單,先例用 `-c' 編出 object 檔,再用 ar 包起來即可. 考慮代碼如下 :
____ hello.c ____
#include
void hello(){ printf("Hello "); }

____ world.c ____
#include
void world(){ printf("world."); }

____ mylib.h ____
void hello();
void world();

進行編譯 :
# gcc -c hello.c world.c
# ar rcs libmylib.a hello.o world.o
<產出 libmylib.a>
這樣就可以建出一個檔名為 libmylib.a 的檔。輸出的檔名其實沒有硬性規定,但如果想要配合 gcc 的 '-l' 參數來連結,一定要以 `lib' 開頭,中間是你要的library名稱,然後緊接著 `.a' 結尾。

* 使用 :
考慮代碼 main_mylib.c :
#include "mylib.h"
int main() {
hello();
world();
}

使用上就像與一般的 object 檔連結沒有差別 :
# gcc main_mylib.c libmylib.a <預設會產出 a.out>
也可以配合gcc 的 `-l' 參數使用 :
client:/home/max/src # gcc main_mylib.c -L. -lmylib <預設會產出 a.out>

`-Ldir' 參數用來指定要搜尋程式庫的目錄,`.' 表示搜尋現在所在的目錄。通常預設會搜 /usr/lib 或 /lib 等目錄。`-llibrary' 參數用來指定要連結的程式庫 ,'mylib' 表示要與mylib進行連結,他會搜尋library名稱前加`lib'後接`.a'的檔案來連結 :
client:/home/max/src # ./a.out

Hello world <成功執行>

Shared libraries :
Shared library 會在程式執行起始時才被自動載入。因為程式庫與執行檔是分離的,所以維護彈性較好。有兩點要注意,shared library是在程式起始時就要被載入,而不是執行中用到才載入,而且在連結階段需要有該程式庫才能進行連結。

首先有一些名詞要弄懂,soname、real name與linker name。

soname 用來表示是一個特定 library 的名稱,像是 libmylib.so.1 。前面以 `lib' 開頭,接著是該 library 的名稱,然後是 `.so' ,接著是版號,用來表名他的介面;如果介面改變時,就會增加版號來維護相容度。

real name 是實際放有library程式的檔案名稱,後面會再加上 minor 版號與release 版號,像是 libmylib.so.1.0.0 。一般來說,版號的改變規則是(印象中在 APress-Difinitive Guide to GCC中有提到,但目前手邊沒這本書),最尾碼的release版號用於程式內容的修正,介面完全沒有改變。中間的minor用於有新增加介面,但相舊介面沒改變,所以與舊版本相容。最前面的version版號用於原介面有移除或改變,與舊版不相容時。

linker name是用於連結時的名稱,是不含版號的 soname ,如: libmylib.so。通常 linker name與 real name是用 ln 指到對應的 real name ,用來提供彈性與維護性。

* 編譯 :
shared library的製作過程較複雜 :
# gcc -c -fPIC hello.c world.c

編譯時要加上 -fPIC 用來產生 position-independent code。也可以用 -fpic參數。 (不太清楚差異,只知道 -fPIC 較通用於不同平台,但產生的code較大,而且編譯速度較慢)。
# gcc -shared -WI,-soname,libmylib.so.1 -o libmylib.so1.0.0 hello.o world.o

-shared 表示要編譯成 shared library
-Wl 用於參遞參數給linker,因此-soname與libmylib.so.1會被傳給linker處理。
-soname用來指名 soname 為 limylib.so.1

library會被輸出成libmylib.so.1.0.0 (也就是real name)若不指定 soname 的話,在編譯結連後的執行檔會以連時的library檔名為soname,並載入他。否則是載入soname指定的library檔案。

在編譯後再用 ln 來建立 soname 與 linker name 兩個檔案 :
# ln -s libmylib.so1.0.0 libmylib.so
# ln -s libmylib.so1.0.0 libmylib.so.1

* 使用 :
與使用 static library 同 :
# gcc main_mylib.c libmylib.so

或用
# gcc main_mylib.c -L. -lmylib

如果目錄下同時有static與shared library的話,會以shared為主, 可以使用 -static 參數可以避免使用shared連結 :
# gcc main_mylib.c -static -L. -lmylib <會花比用 shared library 久的時間>

此時可以用 ldd 看編譯出的執行檔與shared程式庫的相依性 :
# ldd ./a.out
linux-gate.so.1 => (0xffffe000)
libmylib.so => not found
libc.so.6 => /lib/libc.so.6 (0xb7dda000)
/lib/ld-linux.so.2 (0xb7f0a000)

輸出結果顯示出該執行檔需要 libmylib.so 這個shared library。會顯示 not found 因為沒指定該library所在的目錄,所找不到該library. 執行時會要求載入libmylib.so:
# ./a.out.
/a.out: error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory

因為找不到 libmylib.so.1 所以無法執行程式. 有幾個方式可以處理 :
a. 把 libmylib.so 安裝到系統的library目錄,如/usr/lib下
b. 設定 /etc/ld.so.conf ,加入一個新的library搜尋目錄,並執行ldconfig 更新快取
c. 設定 LD_LIBRARY_PATH 環境變數來搜尋library, 這裡是以加入目前的目錄來搜尋要載作的library

client:/home/max/src # export LD_LIBRARY_PATH=.
client:/home/max/src # ./a.out
Hello world <成功執行>

Dynamically loaded libraries :
Dynamicaaly loaded libraries 才是像 windows 所用的 DLL ,在使用到時才載入,編譯連結時不需要相關的library。動態載入庫常被用於像plug-ins的應用.

* 使用 :
動態載入是透過一套 dl function來處理, 請參考如下 API :

  1. #include
  2. void *dlopen(const char *filename, int flag);
  3. //開啟載入 filename 指定的 library。
  4. void *dlsym(void *handle, const char *symbol);
  5. //取得 symbol 指定的symbol name在library被載入的記憶體位址。
  6. int dlclose(void *handle);
  7. //關閉dlopen開啟的handle。
  8. char *dlerror(void);
  9. //傳回最近所發生的錯誤訊息。
下面範例代碼示範如何使用上述 API :
____ dltest.c ____

  1. #include
  2. #include
  3. #include
  4. int main() {
  5. void *handle;
  6. void (*f)();
  7. char *error;
  8. /* 開啟之前所撰寫的 libmylib.so 程式庫 */
  9. handle = dlopen("./libmylib.so", RTLD_LAZY);
  10. if( !handle ) {
  11. fputs( dlerror(), stderr);
  12. exit(1);
  13. }
  14. /* 取得 hello function 的 address */
  15. f = dlsym(handle, "hello");
  16. if(( error=dlerror())!=NULL) {
  17. fputs(error, stderr);
  18. exit(1);
  19. }
  20. /* 呼叫該 function */
  21. f();
  22. dlclose(handle);
  23. }

編譯時要加上 -ldl 參數來與 dl library 連結 :
# gcc dltest.c -ldl
# ./a.out
Hello <成功執行>





2011年2月21日 星期一

台灣新三寶!太好笑了...

今天在FB上看到的,台灣新三寶!實在太好笑了...
有創意喔!

宅男有三寶:科技、女優、人真好
蘿莉有三寶:身輕、嬌柔、易推倒
型男有三寶:親親、抱抱、再推倒
當兵有三寶:裝死、偷懶、會擺老
坐牢有三寶:彎腰、肥皂、肛肛好
好人有三寶:司機、請客、修電腦
周董有三寶:唉呦、不錯、這個屌
韓劇有三寶:車禍、癌症、醫不好
台客有三寶:拎娘、G8、跨啥小
威武有三寶:蜆精、大鵰、愛福好
謊言有三寶:天長、地久、愛到老
謊言再三寶:海枯、石爛、你最好
房東有三寶:靠北、靠木、你錢沒繳
打架有三寶:單挑、圍毆、我先跑
上課有三寶:發呆、聊天、睡到飽
老師有三寶:劃線、重要、這會考
考試有三寶:小抄、刻字、同學罩
國小有三寶:起立、立正、老師好
國中有三寶:腦殘、白目、愛耍屌
高中有三寶:補習、熬夜、拼聯考
大學生有三寶:複製、貼上、過就好
大學男生有三寶:聯誼、把咩、學妹好
大學女生有三寶:化妝、打扮、穿的少
上班族有三寶:上班、下班、公司倒
交通警察有三寶:行照、駕照、車停好
海綿寶寶有三寶:小蝸、水母、愛蟹堡
海綿寶寶再三寶:章魚、海星、比奇堡
成人頻道有三寶:彩虹、星穎、新東寶
台灣的網路有三寶:斷線、LAG、修不好

2011年1月30日 星期日

找出USB還原Ubuntu+XP的方法

這幾天為了測試Ubuntu10.04+XP光碟開機還原失敗的問題,試驗了好幾種方式:
1. 使用舊版本clonezilla 1.0.5-8nk,但可惜的是,開機順序中斷,跑到command mode下,可能是Kernal舊了,一些周邊驅動也不符合。
2. 之前用clonezilla 1.2.6.24,改用stable中最新1.2.6.59,以新版開機,重做開機iso,失敗!
3. 用clonezilla 1.2.6.59,測試整顆硬碟備份及製作開機還原光碟iso,失敗!
4. 改用Ubuntu支援系列的clonezilla版本,做出的還原開機iso光碟,在啟動時,就當掉!失敗中的失敗!

最後,跑回去以一支16Gb USB來做,之前也試驗過,但似乎在抓取USB時,找不到。而這一次,我反覆執行Clonezilla再生龍,且以指令模式察看,發現在執行過程中,USB並沒有載入,必須得手動先轉換成root mode(sudo su),然後mount -a /dev/sdb /home/partimag 將USB掛載上去(USB 檔案格式需為F32 or F16),然後再結束回到畫面進行還原動作!

ㄟ嘿!居然這樣就成功了。

由於檔案目前作起來不到4Gb,應該以隨身碟模式可以撐一陣子!呵

2011年1月28日 星期五

Super Mario Bros

超級瑪利歐,紅白任天堂經典遊戲 Graphic from http://mario.ngamer.net/
在網上,有人成立官網來記錄這些點滴。真的是相當令人懷念。Graphic from http://mario.ngamer.net/

2011年1月26日 星期三

教室安裝完成Ubuntu10.04+XP雙OS

儘管連夜趕測的Ubuntu10.04+XP的開機光碟,仍然在當天有問題,安裝流程都很成功,Ubuntu開機OK,但XP的開機畫面呈現畢卡索的數碼圖示,表示仍然是有問題。所以,仍然回到用一台USB硬碟Fat32還原,加上用一台硬碟拆機殼對拷的窘境。

儘管這麼艱難,兩位同學(致廷、偉凱)仍然在早上兩個多鐘頭搞定最後的兩排電腦。看來,我得回去利用時間測試問題所在。

2011年1月25日 星期二

尋找一部老片[天使之約]

天使之約,Date with an Angel
小時候看的一部電影,好像是一個人愛上一個受傷的天使,而最後和他的任性女友分手!
這任性女友好像是菲比凱絲(當年的玉女教主)飾演。