創建和使用庫:靜態、共享和動態
作者:Norkai Laboratory
來自:Linux知識寶庫
C語言中有一些函數不需要進行編譯,有一些函數也可以在多個文章中使用。一般來說,
這些函數都會執行一些標準任務,如數據庫輸入 /輸出操作或屏幕控制等??梢允孪葘@些
函數進行編譯,然后將它們放置在一些特殊的目標代碼文件中,這些目標代碼文件就稱為庫。
庫文件中的函數可以通過連接程序與應用程序進行連接。這樣就不必在每次開發程序時都對
這些通用的函數進行編譯了。
不同類型的應用程序將會使用不同的函數庫。例如:libdbm庫中組包含了對數據庫文件
進行訪問的dbm函數,需要對數據庫進行操作的程序就會與該庫進行連接。數學應用程序將
使用數學庫libm,X-Windows應用程序將使用Xlib庫,libX11。另外,所有的程序都將使用
標準的C函數庫。libc,該庫中包含了內存管理或輸入輸出操作的基本函數,這些庫都
存放在/usr/lib這些系統公用的目錄中,系統中的任何用戶都可以利用這些庫。當然用戶也
可以建立自己專用的庫函數,供自己或其它指定的人員使用。
庫可以有三種使用的形式:靜態、共享和動態。靜態庫的代碼在編譯時就已連接到開發
人員開發的應用程序中,而共享庫只是在程序開始運行時才載入,在編譯時,只是簡單地指
定需要使用的庫函數。動態庫則是共享庫的另一種變化形式。動態庫也是在程序運行時載入,
但與共享庫不同的是,使用的庫函數不是在程序運行開始,而是在程序中的語句需要使用該
函數時才載入。動態庫可以在程序運行期間釋放動態庫所占用的內存,騰出空間供其它程序
使用。由于共享庫和動態庫并沒有在程序中包括庫函數的內容,只是包含了對庫函數的引用,
因此代碼的規模比較小。
已經開發的大多數庫都采取共享庫的方式。ELF格式的可執行文件使得共享庫能夠比較容
易地實現,當然使用舊的a.out模式也可以實現庫的共享。Linux系統中目前可執行文件的標準
格式為ELF格式。
GNU庫的使用必須遵守Library GNU Public License(LGPL許可協議)。該協議與GNU許可協
議略有不同,開發人員可以免費使用GNU庫進行軟件開發,但必須保證向用戶提供所用的庫函
數的源代碼。
系統中可用的庫都存放在/usr/lib和/lib目錄中。庫文件名由前綴lib和庫名以及后綴組
成。根據庫的類型不同,后綴名也不一樣。共享庫的后綴名由.so和版本號組成,靜態庫的后
綴名為.a。采用舊的a.out格式的共享庫的后綴名為.sa。
libname.so.major.minor
libname.a
這里的name可以是任何字符串,用來唯一標識某個庫。該字符串可以是一個單字、幾個字
符、甚至一個字母。數學共享庫的庫名為libm.so.5,這里的標識字符為m,版本號為5。libm.a
則是靜態數學庫。X-Windows庫名為libX11.so.6,這里使用X11作為庫的標識,版本號為6。
使用gcc編譯器就可以將庫與自己開發的程序連接起來,例如:libc.so.5中包含了標準的輸
入輸出函數,當連接程序進行目標代碼連接時會自動搜索該程序并將其連接到生成的可執行文件
中。標準的輸入輸出庫中包含了許多基本的輸入輸出函數,如printf函數等。也可以連接其它的
一些系統函數庫,如數學庫等,但與libc.so.5不同,大部分其它的系統庫需要在命令行中顯式
指定所用的庫名。
在/usr/lib和/lib目錄中可以找到絕大多數的共享庫。連接時將首先搜索這兩個目錄。有一
些庫也可能存放在特定的目錄中,在/etc/ld.conf配置文件中給出了這些目錄的列表。連接程序
也會對列出的這些目錄進行搜索。在默認情況下,Linux將首先搜索指定庫的共享版本,如果找
不到,才會去搜索靜態版本。在對共享庫進行更新或安裝新庫后,必須運行ldconfig命令更新
/etc/ld.conf文件中相應的項(如果使用RPM進行安裝,一般會自動進行更新,不過也不能保證
這一點)。
在gcc編譯器中引用可搜索到的目錄中的庫文件時,需要使用-l選項和庫名。在gcc命令行上
輸入-lm可以在程序中連接標準算術庫,-l將首先使用libname.so進行搜索,這里是libm.so。下
面的例子將使用算術庫創建bookrecs程序,請注意這里的-lm選項。
$ gcc main.c io.c -o bookrecs -lm
系統中還有一些其它可用的庫,常用的是libncurses.a庫,包含了一些簡單的鼠標移動例程。
在命令行中使用-lncurses選項引用libncurses.so庫。下面的例子同時調用了數學和光標庫。
$ gcc mian.c io.c -o bookrecs -lm -lncurses
在引用其它目錄中的庫時,需要使用-ldir選項指定該目錄。該選項指定了搜索庫函數時其
它路徑。在下面的例子中,用戶在連接時使用了mydir目錄中的myio.so庫文件。
$ gcc main.c -o bookrecs -lmydir -lmyio (http://www.fanqiang.com)
a的是為了支持較老的a.out格式的可執行文件的
.so的是支持elf格式的可執行文件的庫。
靜態庫是指編譯連接時,把庫文件的代碼全部加入到可執行文件中,所以生成的文件較大,
但運行時,就不再需要庫文件了。動態庫正好相反,在編譯連接時,沒有把庫文件的代碼加入
到可執行文件中,所以生成的文件較小,但運行時,仍需要加載庫文件
.a是靜態庫文件,可以用ar 命令生成。
.so是動態庫文件,編譯時加上指定的選項即可生成,具體選項看相應的系統文檔了。。。。
IBM AIX下如下:
$(CC) $(SHOPT) $(SHLIBS) a.o b.o -o lib$@$(DBBUILDTAIL)
假設你有test1.c test2.c test3.c , 編寫成動態鏈接庫
1. 先編譯成test1.o test2.o test3.o
2. gcc -shared -W1, -soname,libvTest.so.1 -o libvTest.so.1.0 *.o
我給你一篇文章吧,是IBM公司的人寫的,我就是照著里面做的,另外你可以采用C++的方
式寫,然后再套一層C寫SO,最后可供外部以C的方式調用。還有一種方法就是將C++編寫的SO
以C++的方式提供給外界使用,就是在外部程序中引入類的聲明及變量實例,就好象外部程序
也是其中一部分一樣。