當(dāng)前位置:首頁(yè) > 智能硬件 > 智能硬件
[導(dǎo)讀]自學(xué)c編譯器的朋友都知道。c編譯器作為常用軟件之一,并非具備無(wú)法逾越難度。對(duì)于c編譯器的學(xué)習(xí),往往需要具備一定耐心。本文對(duì)c編譯器的講解基于gcc c編譯器,同時(shí)本文承接“c編譯器so easy,gcc c編譯器生成、使用動(dòng)靜態(tài)庫(kù)(上篇)”一文而談,不了解的朋友可以先回顧一番哦。

自學(xué)c編譯器的朋友都知道。c編譯器作為常用軟件之一,并非具備無(wú)法逾越難度。對(duì)于c編譯器的學(xué)習(xí),往往需要具備一定耐心。本文對(duì)c編譯器的講解基于gcc c編譯器,同時(shí)本文承接“c編譯器so easy,gcc c編譯器生成、使用動(dòng)靜態(tài)庫(kù)(上篇)”一文而談,不了解的朋友可以先回顧一番哦。此外,本文主要內(nèi)容為gcc生成靜態(tài)和動(dòng)態(tài)鏈接庫(kù)的示例,一起來(lái)了解下吧。

我們通常把一些公用函數(shù)制作成函數(shù)庫(kù),供其它程序使用。函數(shù)庫(kù)分為靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)兩種。

靜態(tài)庫(kù)在程序編譯時(shí)會(huì)被連接到目標(biāo)代碼中,程序運(yùn)行時(shí)將不再需要該靜態(tài)庫(kù)。

動(dòng)態(tài)庫(kù)在程序編譯時(shí)并不會(huì)被連接到目標(biāo)代碼中,而是在程序運(yùn)行是才被載入,因此在程序運(yùn)行時(shí)還需要?jiǎng)討B(tài)庫(kù)存在。

本文主要通過(guò)舉例來(lái)說(shuō)明在Linux中如何創(chuàng)建靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù),以及使用它們。

為了便于闡述,我們先做一部分準(zhǔn)備工作。

1.準(zhǔn)備好測(cè)試代碼hello.h、hello.c和main.c

hello.h(見(jiàn)程序1)為該函數(shù)庫(kù)的頭文件。

hello.c(見(jiàn)程序2)是函數(shù)庫(kù)的源程序,其中包含公用函數(shù)hello,該函數(shù)將在屏幕上輸出“Hello XXX!”。

main.c(見(jiàn)程序3)為測(cè)試庫(kù)文件的主程序,在主程序中調(diào)用了公用函數(shù)hello。

程序1: hello.h

#ifndef HELLO_H

#define HELLO_H

void hello(const char *name);

#endif

程序2:hello.c#include

void hello(const char *name) {

printf(“Hello %s!\n”, name);

}

程序3:main.c#include “hello.h”

int main()

{

hello(“everyone”);

return 0;

}

2.問(wèn)題的提出

注意:這個(gè)時(shí)候,我們編譯好的hello.o是無(wú)法通過(guò)gcc –o 編譯的,這個(gè)道理非常簡(jiǎn)單,

hello.c是一個(gè)沒(méi)有main函數(shù)的.c程序,因此不夠成一個(gè)完整的程序,如果使用gcc –o 編譯并連接它,GCC將報(bào)錯(cuò)。

無(wú)論靜態(tài)庫(kù),還是動(dòng)態(tài)庫(kù),都是由.o文件創(chuàng)建的。因此,我們必須將源程序hello.c通過(guò)gcc先編譯成.o文件。

這個(gè)時(shí)候我們有三種思路:

1) 通過(guò)編譯多個(gè)源文件,直接將目標(biāo)代碼合成一個(gè).o文件。

2) 通過(guò)創(chuàng)建靜態(tài)鏈接庫(kù)libmyhello.a,使得main函數(shù)調(diào)用hello函數(shù)時(shí)可調(diào)用靜態(tài)鏈接庫(kù)。

3) 通過(guò)創(chuàng)建動(dòng)態(tài)鏈接庫(kù)libmyhello.so,使得main函數(shù)調(diào)用hello函數(shù)時(shí)可調(diào)用靜態(tài)鏈接庫(kù)。

3.思路一:編譯多個(gè)源文件

在系統(tǒng)提示符下鍵入以下命令得到hello.o文件。

# gcc -c hello.c

為什么不使用gcc–o hello hello.cpp 這個(gè)道理我們之前已經(jīng)說(shuō)了,使用-c是什么意思呢?這涉及到gcc 編譯選項(xiàng)的常識(shí)。

我們通常使用的gcc –o 是將.c源文件編譯成為一個(gè)可執(zhí)行的二進(jìn)制代碼(-o選項(xiàng)其實(shí)是制定輸出文件文件名,如果不加-c選項(xiàng),gcc默認(rèn)會(huì)編譯連接生成可執(zhí)行文件,文件的名稱有-o選項(xiàng)指定),這包括調(diào)用作為GCC內(nèi)的一部分真正的C編譯器(ccl),以及調(diào)用GNU C編譯器的輸出中實(shí)際可執(zhí)行代碼的外部GNU匯編器(as)和連接器工具(ld)。

而gcc –c是使用GNU匯編器將源文件轉(zhuǎn)化為目標(biāo)代碼之后就結(jié)束,在這種情況下,只調(diào)用了C編譯器(ccl)和匯編器(as),而連接器(ld)并沒(méi)有被執(zhí)行,所以輸出的目標(biāo)文件不會(huì)包含作為L(zhǎng)inux程序在被裝載和執(zhí)行時(shí)所必須的包含信息,但它可以在以后被連接到一個(gè)程序。

我們運(yùn)行l(wèi)s命令看看是否生存了hello.o文件。

# ls

hello.c hello.h hello.o main.c

在ls命令結(jié)果中,我們看到了hello.o文件,本步操作完成。

同理編譯main

#gcc –c main.c

將兩個(gè)文件鏈接成一個(gè).o文件。

#gcc –o hello hello.o main.o

運(yùn)行

# 。/hello

Hello everyone!

4.思路二:靜態(tài)鏈接庫(kù)

下面我們先來(lái)看看如何創(chuàng)建靜態(tài)庫(kù),以及使用它。

靜態(tài)庫(kù)文件名的命名規(guī)范是以lib為前綴,緊接著跟靜態(tài)庫(kù)名,擴(kuò)展名為.a。例如:我們將創(chuàng)建的靜態(tài)庫(kù)名為myhello,則靜態(tài)庫(kù)文件名就是libmyhello.a。在創(chuàng)建和使用靜態(tài)庫(kù)時(shí),需要注意這點(diǎn)。創(chuàng)建靜態(tài)庫(kù)用ar命令。

在系統(tǒng)提示符下鍵入以下命令將創(chuàng)建靜態(tài)庫(kù)文件libmyhello.a。

# ar rcs libmyhello.a hello.o

我們同樣運(yùn)行l(wèi)s命令查看結(jié)果:

# ls

hello.c hello.h hello.o libmyhello.a main.c

ls命令結(jié)果中有l(wèi)ibmyhello.a。

靜態(tài)庫(kù)制作完了,如何使用它內(nèi)部的函數(shù)呢?只需要在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標(biāo)文件時(shí)指明靜態(tài)庫(kù)名,gcc將會(huì)從靜態(tài)庫(kù)中將公用函數(shù)連接到目標(biāo)文件中。注意,gcc會(huì)在靜態(tài)庫(kù)名前加上前綴lib,然后追加擴(kuò)展名.a得到的靜態(tài)庫(kù)文件名來(lái)查找靜態(tài)庫(kù)文件,因此,我們?cè)趯懶枰B接的庫(kù)時(shí),只寫名字就可以,如libmyhello.a的庫(kù),只寫:-lmyhello

在程序3:main.c中,我們包含了靜態(tài)庫(kù)的頭文件hello.h,然后在主程序main中直接調(diào)用公用函數(shù)hello。下面先生成目標(biāo)程序hello,然后運(yùn)行hello程序看看結(jié)果如何。

# gcc -o hello main.c -static -L. -lmyhello

# 。/hello

Hello everyone!

我們刪除靜態(tài)庫(kù)文件試試公用函數(shù)hello是否真的連接到目標(biāo)文件 hello中了。

# rm libmyhello.a

rm: remove regular file `libmyhello.a‘? y

# 。/hello

Hello everyone!

程序照常運(yùn)行,靜態(tài)庫(kù)中的公用函數(shù)已經(jīng)連接到目標(biāo)文件中了。

靜態(tài)鏈接庫(kù)的一個(gè)缺點(diǎn)是,如果我們同時(shí)運(yùn)行了許多程序,并且它們使用了同一個(gè)庫(kù)函數(shù),這樣,在內(nèi)存中會(huì)大量拷貝同一庫(kù)函數(shù)。這樣,就會(huì)浪費(fèi)很多珍貴的內(nèi)存和存儲(chǔ)空間。使用了共享鏈接庫(kù)的Linux就可以避免這個(gè)問(wèn)題。

共享函數(shù)庫(kù)和靜態(tài)函數(shù)在同一個(gè)地方,只是后綴有所不同。比如,在一個(gè)典型的Linux系統(tǒng),標(biāo)準(zhǔn)的共享數(shù)序函數(shù)庫(kù)是/usr/lib/libm.so。

當(dāng)一個(gè)程序使用共享函數(shù)庫(kù)時(shí),在連接階段并不把函數(shù)代碼連接進(jìn)來(lái),而只是鏈接函數(shù)的一個(gè)引用。當(dāng)最終的函數(shù)導(dǎo)入內(nèi)存開始真正執(zhí)行時(shí),函數(shù)引用被解析,共享函數(shù)庫(kù)的代碼才真正導(dǎo)入到內(nèi)存中。這樣,共享鏈接庫(kù)的函數(shù)就可以被許多程序同時(shí)共享,并且只需存儲(chǔ)一次就可以了。共享函數(shù)庫(kù)的另一個(gè)優(yōu)點(diǎn)是,它可以獨(dú)立更新,與調(diào)用它的函數(shù)毫不影響。

5.思路三、動(dòng)態(tài)鏈接庫(kù)(共享函數(shù)庫(kù))

我們繼續(xù)看看如何在Linux中創(chuàng)建動(dòng)態(tài)庫(kù)。我們還是從.o文件開始。

動(dòng)態(tài)庫(kù)文件名命名規(guī)范和靜態(tài)庫(kù)文件名命名規(guī)范類似,也是在動(dòng)態(tài)庫(kù)名增加前綴lib,但其文件擴(kuò)展名為.so。例如:我們將創(chuàng)建的動(dòng)態(tài)庫(kù)名為myhello,則動(dòng)態(tài)庫(kù)文件名就是libmyhello.so。用gcc來(lái)創(chuàng)建動(dòng)態(tài)庫(kù)。

在系統(tǒng)提示符下鍵入以下命令得到動(dòng)態(tài)庫(kù)文件libmyhello.so。

# gcc -shared -fPIC -o libmyhello.so hello.o

“PIC”命令行標(biāo)記告訴GCC產(chǎn)生的代碼不要包含對(duì)函數(shù)和變量具體內(nèi)存位置的引用,這是因?yàn)楝F(xiàn)在還無(wú)法知道使用該消息代碼的應(yīng)用程序會(huì)將它連接到哪一段內(nèi)存地址空間。這樣編譯出的hello.o可以被用于建立共享鏈接庫(kù)。建立共享鏈接庫(kù)只需要用GCC的”-shared”標(biāo)記即可。

我們照樣使用ls命令看看動(dòng)態(tài)庫(kù)文件是否生成。

# ls

hello.cpp hello.h hello.o libmyhello.so main.cpp

調(diào)用動(dòng)態(tài)鏈接庫(kù)編譯目標(biāo)文件。

在程序中使用動(dòng)態(tài)庫(kù)和使用靜態(tài)庫(kù)完全一樣,也是在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標(biāo)文件時(shí)指明動(dòng)態(tài)庫(kù)名進(jìn)行編譯。我們先運(yùn)行g(shù)cc命令生成目標(biāo)文件,再運(yùn)行它看看結(jié)果。

如果直接用如下方法進(jìn)行編譯,并連接:

# gcc -o hello main.c -L. -lmyhello

(使用”-lmyhello”標(biāo)記來(lái)告訴GCC驅(qū)動(dòng)程序在連接階段引用共享函數(shù)庫(kù)libmyhello.so。”-L.”標(biāo)記告訴GCC函數(shù)庫(kù)可能位于當(dāng)前目錄。否則GNU連接器會(huì)查找標(biāo)準(zhǔn)系統(tǒng)函數(shù)目錄:它先后搜索1.elf文件的 DT_RPATH段—2.環(huán)境變量LD_LIBRARY_PATH—3./etc/ld.so.cache文件列表—4./lib/,/usr/lib目錄找到庫(kù)文件后將其載入內(nèi)存,但是我們生成的共享庫(kù)在當(dāng)前文件夾下,并沒(méi)有加到上述的4個(gè)路徑的任何一個(gè)中,因此,執(zhí)行后會(huì)出現(xiàn)錯(cuò)誤)

# 。/hello

。/hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

#

錯(cuò)誤提示,找不到動(dòng)態(tài)庫(kù)文件libmyhello.so。程序在運(yùn)行時(shí),會(huì)在/usr/lib和/lib等目錄中查找需要的動(dòng)態(tài)庫(kù)文件。若找到,則載入動(dòng)態(tài)庫(kù),否則將提示類似上述錯(cuò)誤而終止程序運(yùn)行。有多種方法可以解決,

(1)我們將文件 libmyhello.so復(fù)制到目錄/usr/lib中,再試試。

# mv libmyhello.so /usr/lib

# 。/hello

成功!

(2)既然連接器會(huì)搜尋LD_LIBRARY_PATH所指定的目錄,那么我們可以將這個(gè)環(huán)境變量設(shè)置成當(dāng)前目錄:

先執(zhí)行:

export LD_LIBRARY_PATH=$(pwd)

再執(zhí)行:

。/hello

成功!

(3)執(zhí)行:

ldconfig /usr/zhsoft/lib

注: 當(dāng)用戶在某個(gè)目錄下面創(chuàng)建或拷貝了一個(gè)動(dòng)態(tài)鏈接庫(kù),若想使其被系統(tǒng)共享,可以執(zhí)行一下“ldconfig 目錄名”這個(gè)命令。此命令的功能在于讓ldconfig將指定目錄下的動(dòng)態(tài)鏈接庫(kù)被系統(tǒng)共享起來(lái),意即:在緩存文件/etc/ld.so.cache中追加進(jìn)指定目錄下的共享庫(kù)。本例讓系統(tǒng)共享了/usr/zhsoft/lib目錄下的動(dòng)態(tài)鏈接庫(kù)。該命令會(huì)重建/etc/ld.so.cache文件。

以上便是此次小編帶來(lái)的“c編譯器”相關(guān)內(nèi)容,通過(guò)本文,希望大家對(duì)gcc生成靜態(tài)和動(dòng)態(tài)鏈接庫(kù)的過(guò)程具備一定的了解。如果你喜歡本文,不妨持續(xù)關(guān)注我們網(wǎng)站哦,小編將于后期帶來(lái)更多精彩內(nèi)容。最后,十分感謝大家的閱讀,have a nice day!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉