日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux系统下的“静态库和动态库”专题之二:库的创建和使用

發(fā)布時間:2023/12/15 linux 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux系统下的“静态库和动态库”专题之二:库的创建和使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

接上文【linux系統(tǒng)下的“靜態(tài)庫和動態(tài)庫”專題之一:庫的概念和規(guī)則】所述,我們通常把一些公用函數(shù)制作成函數(shù)庫,供其它程序使用。函數(shù)庫分為靜態(tài)庫和動態(tài)庫兩種。

– 靜態(tài)庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態(tài)庫。
– 動態(tài)庫在程序編譯時并不會被連接到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態(tài)庫存在。

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

在創(chuàng)建函數(shù)庫前,我們先來準備舉例用的源程序,并將函數(shù)庫的源程序編譯成.o文件。

第1步:編輯源程序代碼

本實例中需要用到3個源程序:hello.h、hello.c和main.c。

– hello.h(見程序1)為該函數(shù)庫的頭文件。
– hello.c(見程序2)是函數(shù)庫的源程序,其中包含公用函數(shù)hello,該函數(shù)將在屏幕上輸出”Hello XXX!”。
– main.c(見程序3)為測試庫文件的主程序,在主程序中調(diào)用了公用函數(shù)hello。

下面附上全部的源代碼內(nèi)容,便于大家自己學(xué)習(xí)測試。

【程序1: hello.h】

#ifndef HELLO_H #define HELLO_Hvoid hello(const char *name);#endif //HELLO_H

【程序2: hello.c】

#include "stdio.h"void hello(const char *name) {printf("Hello %s!\n", name); }

【程序3: main.c】

#include "hello.h"int main() {hello("everyone");return 0; }

第2步:將hello.c編譯成.o文件

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

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

# gcc -c hello.c

注1:本文不介紹各命令使用和其參數(shù)功能,若希望詳細了解它們,請參考其他文檔。
注2:首字符”#”是系統(tǒng)提示符,不需要鍵入,下文相同。

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

# ls hello.c hello.h hello.o main.c

在ls命令結(jié)果中,我們看到了hello.o文件,本步操作完成。
下面我們先來看看如何創(chuàng)建靜態(tài)庫,以及使用它。

第3步:由.o文件創(chuàng)建靜態(tài)庫

靜態(tài)庫文件名的命名規(guī)范是以lib為前綴,緊接著跟靜態(tài)庫名,擴展名為.a。
例如:我們將創(chuàng)建的靜態(tài)庫名為myhello,則靜態(tài)庫文件名就是libmyhello.a。

創(chuàng)建靜態(tài)庫用ar命令。

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

# ar cr libmyhello.a hello.o

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

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

可以看到靜態(tài)庫libmyhello.a已經(jīng)創(chuàng)建成功。

第4步:在程序中使用靜態(tài)庫

靜態(tài)庫制作完了,如何使用它內(nèi)部的函數(shù)呢?

很簡單,只需要在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標文件時指明靜態(tài)庫名,gcc將會從靜態(tài)庫中將公用函數(shù)連接到目標文件中。

注意,gcc會在靜態(tài)庫名前加上前綴lib,然后追加擴展名.a得到的靜態(tài)庫文件名來查找靜態(tài)庫文件。

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

# gcc -o hello main.c -L. -lmyhello # ./hello Hello everyone!

可以看到,程序運行成功了!

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

# rm libmyhello.a rm: remove regular file `libmyhello.a'? y # ./hello Hello everyone!

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

OK。靜態(tài)庫的使用介紹到此為止。我們接下來看下如何在Linux中創(chuàng)建動態(tài)庫。我們還是從.o文件開始。

第5步:由.o文件創(chuàng)建動態(tài)庫文件

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

要注意的是,創(chuàng)建靜態(tài)庫不再使用ar命令,而是gcc命令。

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

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

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

# ls hello.c hello.h hello.o libmyhello.so main.c

可以看到,動態(tài)庫已經(jīng)生成成功了。

第6步:在程序中使用動態(tài)庫

在程序中使用動態(tài)庫和使用靜態(tài)庫完全一樣,也是在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標文件時指明動態(tài)庫名進行編譯。

我們先運行g(shù)cc命令生成目標文件,再運行它看看結(jié)果。

# gcc -o hello main.c -L. -lmyhello # ./hello ./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

哦!出錯了。

看看錯誤提示,原來是找不到動態(tài)庫文件libmyhello.so。
這里要說明一下,linux 系統(tǒng)下有一個潛規(guī)則,程序在運行時,會自動從/usr/lib和/lib等目錄中查找需要的動態(tài)庫文件。若找到,則載入動態(tài)庫,啟動程序開始運行。若找不到,則提示類似上述錯誤而終止程序運行。

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

# mv libmyhello.so /usr/lib # ./hello ./hello: error while loading shared libraries: /usr/lib/libhello.so: cannot restore segment prot after reloc: Permission denied

仍然存在問題!
百度一下,可以看到,這個問題是由于SELinux引起。具體原因在此就不做詳細分析,如果有興趣可以自己百度。這里只給出參考解決方案:

方案一:

編輯/etc/selinux/config,找到這段:

# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - SELinux is fully disabled. SELINUX=enforcing

把SELINUX=enforcing注釋掉:然后新加一行為:

#SELINUX=enforcing SELINUX=disabled

保存,關(guān)閉。

編輯/etc/sysconfig/selinux,找到:

# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - SELinux is fully disabled. SELINUX=enforcing

同樣把SELINUX=enforcing注釋掉:然后新加一行為:

#SELINUX=enforcing SELINUX=disabled

保存,關(guān)閉。

方案二:

# chcon -t texrel_shlib_t /usr/lib/libhello.so

以上兩個方案,任選一個均可。但是不保證能兼容所有系統(tǒng),所以如果有同學(xué)執(zhí)行了方案一,仍然會出錯,則繼續(xù)執(zhí)行方案二。這樣應(yīng)該能解決了。

解決完后,重新運行程序:

# ./hello Hello everyone!

成功了。這也進一步說明了動態(tài)庫在程序運行時是需要的。

第7步:靜態(tài)庫和動態(tài)庫并存的情況

我們回過頭看看,發(fā)現(xiàn)使用靜態(tài)庫和使用動態(tài)庫編譯成目標程序使用的gcc命令完全一樣,那當(dāng)靜態(tài)庫和動態(tài)庫同名時,gcc命令會使用哪個庫文件呢?抱著對問題必究到底的心情,來試試看。

先把所有除.c和.h外的文件全部刪除,恢復(fù)成我們剛剛編輯完舉例程序的狀態(tài)。

# rm -f hello hello.o /usr/lib/libmyhello.so # ls hello.c hello.h main.c

再來創(chuàng)建靜態(tài)庫文件libmyhello.a和動態(tài)庫文件libmyhello.so。

# gcc -c hello.c # ar cr libmyhello.a hello.o # gcc -shared -fPCI -o libmyhello.so hello.o # ls hello.c hello.h hello.o libmyhello.a libmyhello.so main.c

通過上述最后一條ls命令,可以發(fā)現(xiàn)靜態(tài)庫文件libmyhello.a和動態(tài)庫文件libmyhello.so都已經(jīng)生成,并都在當(dāng)前目錄中。然后,我們運行g(shù)cc命令來使用函數(shù)庫myhello生成目標文件hello,并運行程序 hello。

# gcc -o hello main.c -L. -lmyhello # ./hello ./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

從程序hello運行的結(jié)果中很容易知道,當(dāng)靜態(tài)庫和動態(tài)庫同名時, gcc命令將優(yōu)先使用動態(tài)庫。

OK。今天關(guān)于如何在linux系統(tǒng)下生成和使用靜態(tài)庫以及動態(tài)庫的話題,就先聊到這里。有任何問題,歡迎大家隨時留言和聯(lián)系。

總結(jié)

以上是生活随笔為你收集整理的linux系统下的“静态库和动态库”专题之二:库的创建和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。