Linux鏈接,靜態(tài)庫和動(dòng)態(tài)庫教學(xué)教材_第1頁
Linux鏈接,靜態(tài)庫和動(dòng)態(tài)庫教學(xué)教材_第2頁
Linux鏈接,靜態(tài)庫和動(dòng)態(tài)庫教學(xué)教材_第3頁
Linux鏈接,靜態(tài)庫和動(dòng)態(tài)庫教學(xué)教材_第4頁
Linux鏈接,靜態(tài)庫和動(dòng)態(tài)庫教學(xué)教材_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、Good is good, but better carries it.精益求精,善益求善。Linux鏈接,靜態(tài)庫和動(dòng)態(tài)庫-Linux鏈接,靜態(tài)庫和動(dòng)態(tài)庫Filename:Linux鏈接,靜態(tài)庫和動(dòng)態(tài)庫Version:V1.0Date:12/01/2009Author:S.C.Leon=在Linux中創(chuàng)建靜態(tài)庫和動(dòng)態(tài)庫一、基本概念1.1什么是庫在windows平臺和linux平臺下都大量存在著庫。本質(zhì)上來說庫是一種可執(zhí)行代碼的二進(jìn)制形式,可以被操作系統(tǒng)載入內(nèi)存執(zhí)行。由于windows和linux的平臺不同(主要是編譯器、匯編器和連接器的不同),因此二者庫的二進(jìn)制是不兼容的。本文僅限于介紹lin

2、ux下的庫。1.2庫的種類linux下的庫有兩種:靜態(tài)庫和共享庫(動(dòng)態(tài)庫)。二者的不同點(diǎn)在于代碼被載入的時(shí)刻不同。靜態(tài)庫的代碼在編譯過程中已經(jīng)被載入可執(zhí)行程序,因此體積較大。共享庫的代碼是在可執(zhí)行程序運(yùn)行時(shí)才載入內(nèi)存的,在編譯過程中僅簡單的引用,因此代碼體積較小。1.3庫存在的意義庫是別人寫好的現(xiàn)有的,成熟的,可以復(fù)用的代碼,你可以使用但要記得遵守許可協(xié)議?,F(xiàn)實(shí)中每個(gè)程序都要依賴很多基礎(chǔ)的底層庫,不可能每個(gè)人的代碼都從零開始,因此庫的存在意義非同尋常。共享庫的好處是,不同的應(yīng)用程序如果調(diào)用相同的庫,那么在內(nèi)存里只需要有一份該共享庫的實(shí)例。1.4庫文件是如何產(chǎn)生的在linux下靜態(tài)庫的后綴是.a

3、,它的產(chǎn)生分兩步Step1.由源文件編譯生成一堆.o,每個(gè).o里都包含這個(gè)編譯單元的符號表Step2.ar命令將很多.o轉(zhuǎn)換成.a,成文靜態(tài)庫動(dòng)態(tài)庫的后綴是.so,它由gcc加特定參數(shù)編譯產(chǎn)生。具體方法參見后文實(shí)例。1.5庫文件是如何命名的,有沒有什么規(guī)范在linux下,庫文件一般放在/usr/lib和/lib下,靜態(tài)庫的名字一般為libxxxx.a,其中xxxx是該lib的名稱動(dòng)態(tài)庫的名字一般為libxxxx.so.major.minor,xxxx是該lib的名稱,major是主版本號,minor是副版本號1.6如何知道一個(gè)可執(zhí)行程序依賴哪些庫ldd命令可以查看一個(gè)可執(zhí)行程序依賴的共享庫,例

4、如#ldd/bin/lnlibc.so.6=/lib/libc.so.6(040021000)/lib/ld-linux.so.2=/lib/ld-linux.so.2(040000000)可以看到ln命令依賴于libc庫和ld-linux庫1.7可執(zhí)行程序在執(zhí)行的時(shí)候如何定位共享庫文件當(dāng)系統(tǒng)加載可執(zhí)行代碼時(shí)候,能夠知道其所依賴的庫的名字,但是還需要知道絕對路徑此時(shí)就需要系統(tǒng)動(dòng)態(tài)載入器(dynamiclinker/loader)對于elf格式的可執(zhí)行程序,是由ld-linux.so*來完成的,它先后搜索elf文件的DT_RPATH段環(huán)境變量LD_LIBRARY_PATH/etc/ld.so.c

5、ache文件列表/lib/,/usr/lib目錄找到庫文件后將其載入內(nèi)存如:exportLD_LIBRARY_PATH=pwd將當(dāng)前文件目錄添加為共享目錄1.8在新安裝一個(gè)庫之后如何讓系統(tǒng)能夠找到他如果安裝在/lib或者/usr/lib下,那么ld默認(rèn)能夠找到,無需其他操作。如果安裝在其他目錄,需要將其添加到/etc/ld.so.cache文件中,步驟如下1.編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑2.運(yùn)行l(wèi)dconfig,該命令會重建/etc/ld.so.cache文件二、實(shí)驗(yàn)設(shè)計(jì)我們通常把一些公用函數(shù)制作成函數(shù)庫,供其它程序使用。函數(shù)庫分為靜態(tài)庫和動(dòng)態(tài)庫兩種。靜態(tài)庫

6、在程序編譯時(shí)會被連接到目標(biāo)代碼中,程序運(yùn)行時(shí)將不再需要該靜態(tài)庫。動(dòng)態(tài)庫在程序編譯時(shí)并不會被連接到目標(biāo)代碼中,而是在程序運(yùn)行是才被載入,因此在程序運(yùn)行時(shí)還需要?jiǎng)討B(tài)庫存在。本文主要通過舉例來說明在Linux中如何創(chuàng)建靜態(tài)庫和動(dòng)態(tài)庫,以及使用它們。為了便于闡述,我們先做一部分準(zhǔn)備工作。2.1準(zhǔn)備好測試代碼hello.h、hello.c和main.c;hello.h(見程序1)為該函數(shù)庫的頭文件。hello.c(見程序2)是函數(shù)庫的源程序,其中包含公用函數(shù)hello,該函數(shù)將在屏幕上輸出HelloXXX!。main.c(見程序3)為測試庫文件的主程序,在主程序中調(diào)用了公用函數(shù)hello。程序1:hel

7、lo.hHYPERLINK/leonsc/archive/2009/12/02/4917816.aspxviewplainHYPERLINK/leonsc/archive/2009/12/02/4917816.aspxcopytoclipboardHYPERLINK/leonsc/archive/2009/12/02/4917816.aspxprintHYPERLINK/leonsc/archive/2009/12/02/4917816.aspx?#ifndefHELLO_H#defineHELLO_Hvoidhello(constchar*name);#endif/HELLO_H程序2:he

8、llo.cHYPERLINK/leonsc/archive/2009/12/02/4917816.aspxviewplainHYPERLINK/leonsc/archive/2009/12/02/4917816.aspxcopytoclipboardHYPERLINK/leonsc/archive/2009/12/02/4917816.aspxprintHYPERLINK/leonsc/archive/2009/12/02/4917816.aspx?#includevoidhello(constchar*name)printf(Hello%s!n,name);程序3:main.cHYPERLI

9、NK/leonsc/archive/2009/12/02/4917816.aspxviewplainHYPERLINK/leonsc/archive/2009/12/02/4917816.aspxcopytoclipboardHYPERLINK/leonsc/archive/2009/12/02/4917816.aspxprintHYPERLINK/leonsc/archive/2009/12/02/4917816.aspx?#includehello.hintmain()hello(everyone);return0;2.2問題的提出注意:這個(gè)時(shí)候,我們編譯好的hello.o是無法通過gcc

10、o編譯的,這個(gè)道理非常簡單,hello.c是一個(gè)沒有main函數(shù)的.c程序,因此不夠成一個(gè)完整的程序,如果使用gcco編譯并連接它,GCC將報(bào)錯(cuò)。無論靜態(tài)庫,還是動(dòng)態(tài)庫,都是由.o文件創(chuàng)建的。因此,我們必須將源程序hello.c通過gcc先編譯成.o文件。這個(gè)時(shí)候我們有三種思路:1)通過編譯多個(gè)源文件,直接將目標(biāo)代碼合成一個(gè).o文件。2)通過創(chuàng)建靜態(tài)鏈接庫libmyhello.a,使得main函數(shù)調(diào)用hello函數(shù)時(shí)可調(diào)用靜態(tài)鏈接庫。3)通過創(chuàng)建動(dòng)態(tài)鏈接庫libmyhello.so,使得main函數(shù)調(diào)用hello函數(shù)時(shí)可調(diào)用靜態(tài)鏈接庫。2.3思路一:編譯多個(gè)源文件在系統(tǒng)提示符下鍵入以下命令得到

11、hello.o文件。#gcc-chello.c為什么不適用gccohellohello.c這個(gè)道理我們之前已經(jīng)說了,使用-c是什么意思呢?這涉及到gcc編譯選項(xiàng)的常識。我們通常使用的gcco是將.c源文件編譯成為一個(gè)可執(zhí)行的二進(jìn)制代碼,這包括調(diào)用作為GCC內(nèi)的一部分真正的C編譯器(ccl),以及調(diào)用GNUC編譯器的輸出中實(shí)際可執(zhí)行代碼的外部GNU匯編器和連接器工具。而gccc是使用GNU匯編器將源文件轉(zhuǎn)化為目標(biāo)代碼之后就結(jié)束,在這種情況下連接器并沒有被執(zhí)行,所以輸出的目標(biāo)文件不會包含作為Linux程序在被裝載和執(zhí)行時(shí)所必須的包含信息,但它可以在以后被連接到一個(gè)程序。我們運(yùn)行l(wèi)s命令看看是否生存

12、了hello.o文件。#lshello.chello.hhello.omain.c在ls命令結(jié)果中,我們看到了hello.o文件,本步操作完成。同理編譯main#gcccmain.c將兩個(gè)文件鏈接成一個(gè).o文件。#gccohellohello.omain.o運(yùn)行#./helloHelloeveryone!完成!2.4思路二:靜態(tài)鏈接庫下面我們先來看看如何創(chuàng)建靜態(tài)庫,以及使用它。靜態(tài)庫文件名的命名規(guī)范是以lib為前綴,緊接著跟靜態(tài)庫名,擴(kuò)展名為.a。例如:我們將創(chuàng)建的靜態(tài)庫名為myhello,則靜態(tài)庫文件名就是libmyhello.a。在創(chuàng)建和使用靜態(tài)庫時(shí),需要注意這點(diǎn)。創(chuàng)建靜態(tài)庫用ar命令。在

13、系統(tǒng)提示符下鍵入以下命令將創(chuàng)建靜態(tài)庫文件libmyhello.a。#arcrlibmyhello.ahello.o我們同樣運(yùn)行l(wèi)s命令查看結(jié)果:#lshello.chello.hhello.olibmyhello.amain.cls命令結(jié)果中有l(wèi)ibmyhello.a。靜態(tài)庫制作完了,如何使用它內(nèi)部的函數(shù)呢?只需要在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標(biāo)文件時(shí)指明靜態(tài)庫名,gcc將會從靜態(tài)庫中將公用函數(shù)連接到目標(biāo)文件中。注意,gcc會在靜態(tài)庫名前加上前綴lib,然后追加擴(kuò)展名.a得到的靜態(tài)庫文件名來查找靜態(tài)庫文件。在程序3:main.c中,我們包含了

14、靜態(tài)庫的頭文件hello.h,然后在主程序main中直接調(diào)用公用函數(shù)hello。下面先生成目標(biāo)程序hello,然后運(yùn)行hello程序看看結(jié)果如何。#gcc-ohellomain.c-L.-lmyhello#./helloHelloeveryone!我們刪除靜態(tài)庫文件試試公用函數(shù)hello是否真的連接到目標(biāo)文件hello中了。#rmlibmyhello.arm:removeregularfilelibmyhello.a?y#./helloHelloeveryone!程序照常運(yùn)行,靜態(tài)庫中的公用函數(shù)已經(jīng)連接到目標(biāo)文件中了。2.5思路三、動(dòng)態(tài)鏈接庫我們繼續(xù)看看如何在Linux中創(chuàng)建動(dòng)態(tài)庫。我們還是從

15、.o文件開始。動(dòng)態(tài)庫文件名命名規(guī)范和靜態(tài)庫文件名命名規(guī)范類似,也是在動(dòng)態(tài)庫名增加前綴lib,但其文件擴(kuò)展名為.so。例如:我們將創(chuàng)建的動(dòng)態(tài)庫名為myhello,則動(dòng)態(tài)庫文件名就是libmyhello.so。用gcc來創(chuàng)建動(dòng)態(tài)庫。在系統(tǒng)提示符下鍵入以下命令得到動(dòng)態(tài)庫文件libmyhello.so。#gcc-shared-fPCI-olibmyhello.sohello.o“PCI”命令行標(biāo)記告訴GCC產(chǎn)生的代碼不要包含對函數(shù)和變量具體內(nèi)存位置的引用,這是因?yàn)楝F(xiàn)在還無法知道使用該消息代碼的應(yīng)用程序會將它連接到哪一段內(nèi)存地址空間。這樣編譯出的hello.o可以被用于建立共享鏈接庫。建立共享鏈接庫只需

16、要用GCC的”-shared”標(biāo)記即可。我們照樣使用ls命令看看動(dòng)態(tài)庫文件是否生成。#lshello.chello.hhello.olibmyhello.somain.c調(diào)用動(dòng)態(tài)鏈接庫編譯目標(biāo)文件。在程序中使用動(dòng)態(tài)庫和使用靜態(tài)庫完全一樣,也是在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標(biāo)文件時(shí)指明動(dòng)態(tài)庫名進(jìn)行編譯。我們先運(yùn)行g(shù)cc命令生成目標(biāo)文件,再運(yùn)行它看看結(jié)果。#gcc-ohellomain.c-L.-lmyhello使用”-lmyhello”標(biāo)記來告訴GCC驅(qū)動(dòng)程序在連接階段引用共享函數(shù)庫libmyhello.so。”-L.”標(biāo)記告訴GCC函數(shù)庫可能位于當(dāng)前目錄。否則GNU連接器會查找標(biāo)準(zhǔn)系統(tǒng)函數(shù)目錄。#./hello./hello:errorwhileloadingsharedlibraries:libmyhello.so:cannotopensharedobjectfile:Nosuchfileordirectory#錯(cuò)誤提示,找不到動(dòng)態(tài)庫文件libmyhello.so。程序在運(yùn)行時(shí),會在/usr/lib和/lib等目錄中查找需要的動(dòng)態(tài)庫文件。若找到,則載入動(dòng)態(tài)庫,否則將提示類似上述錯(cuò)誤而終止程序運(yùn)行。我們將文件libmyhello.so復(fù)制到目錄/usr/lib中,再試

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論