實驗10 編寫庫文件.ppt_第1頁
實驗10 編寫庫文件.ppt_第2頁
實驗10 編寫庫文件.ppt_第3頁
實驗10 編寫庫文件.ppt_第4頁
實驗10 編寫庫文件.ppt_第5頁
已閱讀5頁,還剩18頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、編寫庫文件,為什么要編寫庫文件,每個項目里都有重復(fù)的模塊,造成代碼重復(fù)。 而且,代碼的重用性不好,一旦變化,為了保持設(shè)計的一致性,必須手動逐個修改。 庫文件就是對公共代碼的一種組織形式。 比如,一個用戶驗證功能的庫文件: /userlogin.h文件,提供函數(shù)聲明 int isvaliduser(char* username, int namelen); /userlogin.c文件,實現(xiàn)對用戶信息的驗證 int isvaliduser(char* username, int namelen) int isvalid = 0; /*下面是具體的處理代碼,略去*/ return isvalid

2、,庫文件分類,靜態(tài)庫:程序在編譯時加載庫文件,即靜態(tài)庫代碼在編譯時就拷貝到了程序的代碼段,程序的體積會膨脹。 “以空間換時間”。 動態(tài)庫:程序在運行時加載目標(biāo)代碼,即程序中只保留庫文件的名字和函數(shù)名,在運行時去查找?guī)煳募秃瘮?shù)體,程序的體積基本變化不大。 “以時間換空間”。,靜態(tài)庫的編寫要點,靜態(tài)庫文件的擴展名一般為.a,其編寫步驟為: 編寫函數(shù)代碼 編譯生成各目標(biāo)文件 用ar文件對目標(biāo)文件歸檔,生成靜態(tài)庫文件 注意歸檔文件名必須以lib打頭 使用要點: 在gcc 的-i參數(shù)后加上靜態(tài)庫頭文件的路徑 在gcc 的-l參數(shù)后加上庫文件所在目錄 在gcc 的-l參數(shù)后加上庫文件名,但是要去掉lib

3、和.a擴展名 比如庫文件名是libtest.a 那么參數(shù)就是 -l test,示例編寫靜態(tài)庫,編寫如下兩個文件,注意放在同一目錄中 myalib.h /靜態(tài)庫頭文件 myalib.c /靜態(tài)庫實現(xiàn)文件 /myalib.h 文件的內(nèi)容 void test(); /myalib.c 文件的內(nèi)容 #inlcude void test() printf(testn); ,示例制作靜態(tài)庫,生成目標(biāo)文件 gcc -c myalib.c 執(zhí)行完后會生成一個myalib.o文件 用ar命令歸檔,格式為ar -rc 再次提醒,歸檔文件名一定要以lib打頭, .a結(jié)尾。 ar -rc libtest.a myal

4、ib.o 執(zhí)行完后會生成一個libtest.a文件,示例使用靜態(tài)庫,編寫一個測試程序main.c,內(nèi)容為: #include myalib.h /要把函數(shù)的頭文件包含進來,否則編譯時會報錯 int main(int argc,char* argv) test(); return 0; 編譯目標(biāo)文件,注意要把靜態(tài)庫頭文件的路徑加到-i參數(shù)里面 gcc -i /root/exercise -o main.o -c main.c 生成可執(zhí)行文件,注意要把靜態(tài)庫文件的路徑加到-l參數(shù)里面, 把庫文件名(去掉打頭的lib和結(jié)尾的.a)加到-l參數(shù)后面 gcc -o main -l/root/exerci

5、se main.o ltest 執(zhí)行可執(zhí)行文件查看效果./main,動態(tài)庫的編寫要點,動態(tài)庫一般以.so結(jié)尾,就是shared object的意思 基本生成步驟為: 編寫函數(shù)代碼 編譯生成動態(tài)庫文件,要加上 -shared 和 -fpic 選項,庫文件名以lib開頭, 以.so 結(jié)尾 使用方式分為兩種:隱式調(diào)用和顯示調(diào)用 隱式調(diào)用:類似于靜態(tài)庫的使用,但需修改動態(tài)鏈接庫的配置文件/etc/ld.so.conf 顯示調(diào)用:在主程序里使用dlopen、dlsym、dlerror、dlclose等系統(tǒng)函數(shù),示例編寫動態(tài)庫(與前面一樣),編寫如下兩個文件,注意放在同一目錄中 myalib.h /靜態(tài)庫

6、頭文件 myalib.c /靜態(tài)庫實現(xiàn)文件 /myalib.h 文件的內(nèi)容 void test(); /myalib.c 文件的內(nèi)容 #inlcude void test() printf(testn); ,示例制作,編譯生成動態(tài)庫,庫文件名以lib開頭,以.so 結(jié)尾。 gcc -fpic -shared -o libtest.so myalib.c 此時就生成一個libtest.so文件,示例動態(tài)庫的隱式調(diào)用,1、編寫測試文件,與前面一樣 2、編譯測試程序,與靜態(tài)庫類似,要把頭文件的路徑加到-i參數(shù)里面 gcc -i /root/exercise -o main.o -c main.c 現(xiàn)

7、在生成了一個main.o文件 3、連接生成測試程序,注意要把庫文件的路徑加到-l參數(shù)里面 gcc -o main -l/root/exercise main.o -ltest 現(xiàn)在生成了一個main文件 4、執(zhí)行測試程序 ./main 此時出現(xiàn)提示 ./main: error while loading shared libraries: libtest.so: cannot open shared object file: no such file or directory。 這個原因就是程序運行時并不知道動態(tài)庫所在的路徑,因此自然找不到。解決這個問題的辦法有三種,見下頁,方法一,拷貝動態(tài)鏈

8、接庫到系統(tǒng)共享目錄下,或在系統(tǒng)共享目錄下為該動態(tài)鏈接庫建立連接(硬連接或符號連接均可,常用符號連接)。這里說的系統(tǒng)共享目錄,指的是linux動態(tài)鏈接庫存放的目錄,包括 /lib、/usr、/lib以及/etc/ld.so.conf文件內(nèi)所列的一系列目錄 實例:執(zhí)行 # cp libtest.so /lib # ldconfig 或: # ln -s pwd/libtest.so /lib # ldconfig 注意pwd前后有兩個反引號,其目的是取得pwd命令的輸出,即當(dāng)前目錄。此時再執(zhí)行main,即可成功,方法二,將動態(tài)鏈接庫所在目錄名追加到動態(tài)鏈接庫配置文件/etc/ld.so.conf中

9、 # pwd /etc/ld.so.conf # ldconfig 此時再執(zhí)行main,即可成功,方法三,利用動態(tài)鏈接庫管理命令ldconfig,強制其搜索指定目錄,并更新緩存文件,便于動態(tài)裝入 # ldconfig pwd 此時再執(zhí)行main,即可成功 注意:第三種方法雖然有效,但效果是暫時的,供程序測試還可以,一旦再度運行l(wèi)dconfig,則緩存文件內(nèi)容可能改變,所需的動態(tài)鏈接庫可能不被系統(tǒng)共享了 無論哪種辦法,其實質(zhì)都是用ldconfig命令把動態(tài)庫文件所在路徑加入到系統(tǒng)庫列表中,(前兩種永久,第三種臨時),動態(tài)庫的顯式調(diào)用要點(1),代碼出現(xiàn)庫文件名,用戶需要自己去打開和管理庫文件。要

10、點為: 把dlfcn.h系統(tǒng)頭文件包含進來 用dlopen函數(shù)打開庫文件,并指定打開方式 dllope的的第一個參數(shù)為共享庫的名稱,將會在下面位置查找指定的共享庫。 環(huán)境變量ld_library_path列出分號間隔的所有目錄 文件/etc/ld.so.cache中找到的庫的列表,由ldconfig命令刷新 目錄/usr/lib 目錄/lib 當(dāng)前目錄,動態(tài)庫的顯式調(diào)用要點(2),第二個參數(shù)為打開共享庫的方式。有兩個取值: rtld_now:將共享庫中的所有函數(shù)加載到內(nèi)存 rtld_lazy:會推后共享庫中的函數(shù)的加載操作,直到調(diào)用dlsym()時方加載某函數(shù) 用dlerror()函數(shù)測試是否

11、打開成功,并進行錯誤處理 用dlsym獲得函數(shù)地址,存放在一個函數(shù)指針中 用獲得的函數(shù)指針進行函數(shù)調(diào)用 程序結(jié)束時用dlclose關(guān)閉打開的動態(tài)庫,防止資源泄露 用ldconfig工具把動態(tài)庫的路徑加到系統(tǒng)庫列表中,示例編寫測試文件,示例編譯和執(zhí)行測試文件,編譯測試文件 使用-ldl選項指明生成的對象模塊需要使用共享庫 gcc -o main -ldl main.c 執(zhí)行完后就生成了一個main文件 執(zhí)行測試程序 ./main 輸出 test 說明成功,提示(1),無論是動態(tài)庫的顯式調(diào)用還是隱式調(diào)用,都需要用ldconfig工具將動態(tài)庫的路徑加到系統(tǒng)庫列表中,否則運行時會出錯 可以用ldd命令

12、檢查程序都使用到哪些共享庫,ldd命令行用法如下: ldd -version -v|-verbose -d|-data-relocs -r|-function-relocs -help file. -version : 此選項用于打印出ldd的版本號 -v 或 -verbose : 此選項指示ldd輸出關(guān)于所依賴的動態(tài)鏈接庫的盡可能詳細(xì)的信息 -d 或 -data-relocs : 此選項執(zhí)行重定位,并且顯示不存在的函數(shù). -r 或 -function-relocs : 此選項執(zhí)行數(shù)據(jù)對象與函數(shù)的重定位,同時報告不存在的對象 -help : 此選項用于打印出ldd的幫助信息,提示(2),用靜態(tài)

13、庫連接時的結(jié)果 #ldd main libc.so.6 = /lib/tls/libc.so.6 (0 xb74ad000) /lib/ld-linux.so.2 = /lib/ld-linux.so.2 (0 xb75eb000) 可見使用靜態(tài)庫時,由于庫已經(jīng)被編譯成程序的一部分,因此ldd的輸出中就只有用到的系統(tǒng)庫,提示(3),用動態(tài)庫隱式連接時的結(jié)果 libtest.so = /root/exercise/libtest.so (0 xb75e2000) libc.so.6 = /lib/tls/libc.so.6 (0 xb74ab000) /lib/ld-linux.so.2 = /lib/ld-linux.so.2 (0 xb75eb000) 可見隱式使用動態(tài)庫時,所有用到的動態(tài)庫(包括系統(tǒng)和用戶的)都會被顯示出來,提示(4),動態(tài)庫顯式連接時的結(jié)果 ldd

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論