日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Linux之静态库与动态库20160706

發(fā)布時(shí)間:2025/5/22 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux之静态库与动态库20160706 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

所謂靜態(tài)鏈接是指把要調(diào)用的函數(shù)或者過(guò)程鏈接到可執(zhí)行文件中,成為可執(zhí)行文件的一部分。當(dāng)多個(gè)程序都調(diào)用相同函數(shù)時(shí),內(nèi)存中就會(huì)存在這個(gè)函數(shù)的多個(gè)拷貝,這樣就浪費(fèi)了寶貴的內(nèi)存資源。.so文件是共享庫(kù)文件(動(dòng)態(tài)鏈接)。動(dòng)態(tài)鏈接所調(diào)用的函數(shù)代碼并沒(méi)有被拷貝到應(yīng)用程序的可執(zhí)行文件中去,而是僅僅在其中加入了所調(diào)用函數(shù)的描述信息(往往是一些重定位信息),僅當(dāng)應(yīng)用程序被裝入內(nèi)存開(kāi)始運(yùn)行時(shí),在操作系統(tǒng)的管理下,才在應(yīng)用程序與相應(yīng)的.so之間建立鏈接關(guān)系。

.a文件是多個(gè).o文件的組合。.o文件就是對(duì)象文件,里面包含的內(nèi)容就是01這樣的機(jī)器可執(zhí)行的指令,當(dāng)程序要執(zhí)行時(shí)還需要進(jìn)行鏈接(link).鏈接就是把多個(gè).o文件鏈成一個(gè)可執(zhí)行文件。
關(guān)于庫(kù)生成的問(wèn)題
我們通常把一些公用函數(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ù)存在。
(1)靜態(tài)庫(kù)
簡(jiǎn)單地說(shuō),靜態(tài)庫(kù)是一個(gè)目標(biāo)文件的簡(jiǎn)單集合。因此,首先要解決目標(biāo)文件。
第一步:將各函數(shù)代碼所在的源文件編譯成目錄文件。
例如,對(duì)于myfunc.c, myproc.c
gcc -c myfunc.c myproc.c
將得到myfunc.o和myproc.o。
第二步:由ar(archive,歸檔的意思)把多個(gè)目標(biāo)文件集合起來(lái)。
$ar -r libmyjob.a myfunc.o myproc.o
通常,靜態(tài)庫(kù)的命名方式應(yīng)遵守libXXXXX.a格式。應(yīng)用程序在使用靜態(tài)庫(kù)的時(shí)候,通常只需要把命名中的XXXXX部分傳遞給gcc即可。例如:
$gcc –o mywork –lmyjob …
意為讓gcc(實(shí)際上是gcc調(diào)用ld)去連接一個(gè)名字為libmyjob.a(或者libmyjob.so)的庫(kù)。如果庫(kù)的命名不遵循libXXXXX.a的格式就找不到相應(yīng)文件。
例子:創(chuàng)建靜態(tài)庫(kù)
hello.h為該函數(shù)庫(kù)的頭文件。hello.c是函數(shù)庫(kù)的源程序,其中包含公用函數(shù)hello,該函數(shù)將在屏幕上輸出"
hello XXX!"。main.c為測(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 <stdio.h>
void hello(const char *name)
{
printf("hello %s! \n",name);
}
程序3:
//main.c
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
實(shí)現(xiàn)步驟:
第一步:必須將源程序hello.c通過(guò)gcc先編譯成.o文件,生成hello.o(靜態(tài)庫(kù)/動(dòng)態(tài)庫(kù),都是由.o文件創(chuàng)建的);
第二步:由.o文件創(chuàng)建靜態(tài)庫(kù),生成libmyhello.a(靜態(tài)庫(kù)文件名的命名規(guī)范是以lib為前綴,緊接著跟靜態(tài)庫(kù)名,擴(kuò)展名為.a)創(chuàng)建靜態(tài)庫(kù)用ar命令;
第三步:在程序中使用靜態(tài)庫(kù);(只需要在使用到這些公用函數(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ù)文件)
第四步:刪除靜態(tài)庫(kù)文件,程序照常運(yùn)行,靜態(tài)庫(kù)中的公用函數(shù)hello已經(jīng)連接到目標(biāo)文件main中了。
運(yùn)行:
[root@localhost moduletest]# ls
hello.c hello.h main.c
[root@localhost moduletest]# gcc -c hello.c
[root@localhost moduletest]# ls
hello.c hello.h hello.o main.c
[root@localhost moduletest]# ar crv libmyhello.a hello.o
a - hello.o
[root@localhost moduletest]# ls
hello.c hello.h hello.o libmyhello.a main.c
[root@localhost moduletest]# gcc main.c libmyhello.a -o main
[root@localhost moduletest]# ./main
hello everyone!
[root@localhost moduletest]# rm -f libmyhello.a
[root@localhost moduletest]# ls
hello.c hello.h hello.o main main.c
[root@localhost moduletest]# ./main
hello everyone!
[root@localhost moduletest]#
(2)共享庫(kù)
共享庫(kù)的構(gòu)造復(fù)雜一些,通常是一個(gè)ELF格式的文件。可以有三種方法生成:
$ld -G
$gcc -shared
$libtool
用ld最復(fù)雜,用gcc -share就簡(jiǎn)單的多,但是-share并非在任何平臺(tái)都可以使用。GNU提供了一個(gè)更好的工具libtool,專門(mén)用來(lái)在各種平臺(tái)上生成各種庫(kù)。
用gcc的-shared參數(shù):
gcc –shared –o libmyjob.so myjob.o
這樣,就通過(guò)myjob.o生成了共享庫(kù)文件libmyjob.so。
特別地,在CYGWIN環(huán)境下,仍需要輸出符合Windows命名的共享庫(kù)(動(dòng)態(tài)庫(kù)),即libXXXXX.dll。如:
gcc –shared –o libmyjob.dll myjob.o
例子:創(chuàng)建動(dòng)態(tài)庫(kù)(延用上面的程序1,2,3)
實(shí)現(xiàn)步驟:
第五步:由.o文件創(chuàng)建動(dòng)態(tài)庫(kù)文件(命令:gcc -shared -fPCI -o libmyhello.so hello.o);
第六步:在程序中使用動(dòng)態(tài)庫(kù);(在程序中使用動(dòng)態(tài)庫(kù)和使用靜態(tài)庫(kù)完全一樣,也是在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標(biāo)文件時(shí)指明動(dòng)態(tài)庫(kù)名進(jìn)行編譯。程序在運(yùn)行時(shí),會(huì)在/usr/lib和/lib等目錄中查找需要的動(dòng)態(tài)庫(kù)文件。若找到,則載入動(dòng)態(tài)庫(kù),否則將提示錯(cuò)誤信息而終止程序運(yùn)行。要將文件libmyhello.so復(fù)制到目錄/usr/lib中)
運(yùn)行:
[root@localhost moduletest]# ls
hello.c hello.h hello.o main.c
[root@localhost moduletest]# gcc -shared -fPIC -o libmyhello.so hello.o
[root@localhost moduletest]# ls
hello.c hello.h hello.o libmyhello.so main.c
[root@localhost moduletest]# gcc main.c libmyhello.so -o main
[root@localhost moduletest]# ls
hello.c hello.h hello.o libmyhello.so main main.c
[root@localhost moduletest]# ./main
./main: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory
[root@localhost moduletest]# mv libmyhello.so /usr/lib
可以:
[root@localhost moduletest]# ls
hello.c hello.h hello.o main main.c
[root@localhost moduletest]# ./main
hello everyone!
[root@localhost moduletest]#
或者:
[root@localhost moduletest]# rm -f main
[root@localhost moduletest]# ls
hello.c hello.h hello.o main.c
[root@localhost moduletest]# gcc -Wall -g main.c -lmyhello -o main
[root@localhost moduletest]# ls
hello.c hello.h hello.o main main.c
[root@localhost moduletest]# ./main
hello everyone!
[root@localhost moduletest]#
注意:
當(dāng)靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)同名時(shí), gcc命令將優(yōu)先使用動(dòng)態(tài)庫(kù)。
(3)庫(kù)生成以后的配置
如果要把自己開(kāi)發(fā)的庫(kù)文件安裝到操作系統(tǒng)中,需要有管理員權(quán)限:
(a) 把庫(kù)文件復(fù)制到適當(dāng)?shù)哪夸?#xff1a;
可以把自己開(kāi)發(fā)的動(dòng)態(tài)連接庫(kù)放到/usr/local/lib(或者/usr/lib),或放到其他目錄,但不論放在那里,都必須與LIBRARY_PATH的值、LD_LIBRARY_PATH的值相一致。
(b) 修改相關(guān)的系統(tǒng)配置文件:
修改/etc/ld.so.conf,然后利用/sbin/ldconfig來(lái)完成。
Note:
編譯參數(shù)解析
最主要的是GCC命令行的一個(gè)選項(xiàng):
-shared 該選項(xiàng)指定生成動(dòng)態(tài)連接庫(kù)(讓連接器生成T類型的導(dǎo)出符號(hào)表,有時(shí)候也生成弱連接W類型的導(dǎo)出符號(hào)),不用該標(biāo)志外部程序無(wú)法連接。相當(dāng)于一個(gè)可執(zhí)行文件
l -fPIC:表示編譯為位置獨(dú)立的代碼,不用此選項(xiàng)的話編譯后的代碼是位置相關(guān)的所以動(dòng)態(tài)載入時(shí)是通過(guò)代碼拷貝的方式來(lái)滿足不同進(jìn)程的需要,而不能達(dá)到真正代碼段共享的目的。
l -L.:表示要連接的庫(kù)在當(dāng)前目錄中
l -ltest:編譯器查找動(dòng)態(tài)連接庫(kù)時(shí)有隱含的命名規(guī)則,即在給出的名字前面加上lib,后面加上.so來(lái)確定庫(kù)的名稱
l LD_LIBRARY_PATH:這個(gè)環(huán)境變量指示動(dòng)態(tài)連接器可以裝載動(dòng)態(tài)庫(kù)的路徑。
l 當(dāng)然如果有root權(quán)限的話,可以修改/etc/ld.so.conf文件,然后調(diào)用 /sbin/ldconfig來(lái)達(dá)到同樣的目的,不過(guò)如果沒(méi)有root權(quán)限,那么只能采用輸出LD_LIBRARY_PATH的方法了。
調(diào)用動(dòng)態(tài)庫(kù)的時(shí)候有幾個(gè)問(wèn)題會(huì)經(jīng)常碰到,有時(shí),明明已經(jīng)將庫(kù)的頭文件所在目錄 通過(guò) “-I” include進(jìn)來(lái)了,庫(kù)所在文件通過(guò) “-L”參數(shù)引導(dǎo),并指定了“-l”的庫(kù)名,但通過(guò)ldd命令察看時(shí),就是死活找不到你指定鏈接的so文件,這時(shí)你要作的就是通過(guò)修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件來(lái)指定動(dòng)態(tài)庫(kù)的目錄。通常這樣做就可以解決庫(kù)無(wú)法鏈接的問(wèn)題了。

轉(zhuǎn)載于:https://www.cnblogs.com/yuweifeng/p/5644560.html

總結(jié)

以上是生活随笔為你收集整理的Linux之静态库与动态库20160706的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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