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

歡迎訪問 生活随笔!

生活随笔

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

linux

【转】Linux 静态库与共享库的使用

發(fā)布時(shí)間:2024/1/17 linux 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】Linux 静态库与共享库的使用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文網(wǎng)址:http://blog.csdn.net/heyabo/article/details/11688517

申明: 正如題如示,本篇講的是Linux下是靜態(tài)庫與共享庫,而Window下的動態(tài)鏈接庫詳細(xì)情況可見這篇文章:windows動態(tài)鏈接庫 DLL 淺析。雖然原理,思想差不多,但是細(xì)節(jié)卻各有不同。

?

一、靜態(tài)庫

?

? 1、概念:靜態(tài)庫指將所有相關(guān)的目標(biāo)文件打包成為一個(gè)單獨(dú)的文件-即靜態(tài)庫文件,以.a結(jié)尾。靜態(tài)庫可作為鏈接器的輸入,鏈接器會將程序中使用的到函數(shù)的代碼從庫文件中拷貝到應(yīng)用程序中。一旦鏈接完成,在執(zhí)行程序的時(shí)候就不需要靜態(tài)庫了注1:由于每個(gè)使用靜態(tài)庫的應(yīng)用程序都需要拷貝所用函數(shù)的代碼,所以靜態(tài)鏈接的文件會比較大。 注2:在Unix系統(tǒng)中,靜態(tài)庫以一種稱為存檔(archive)的特殊文件格式存放在磁盤中。存檔文件是一組連接起來的可重定位目標(biāo)文件的集合,有一個(gè)頭部用來描述每個(gè)成員目標(biāo)文件的大小和位置(存檔文件名由后綴.a標(biāo)識)。 2、創(chuàng)建與應(yīng)用 假設(shè)我們想在一個(gè)叫做libvector.a的靜態(tài)庫中提供以下向量函數(shù): [cpp]?view plaincopyprint?
  • ?//?addvec.c??
  • void?addvec(int*?x,?int*?y,?int*z,?int?n)??
  • {??
  • ?????int?i=0;??
  • ?????for(;?i<?n;++i)??
  • ??????????z[i]?=?x[i]?+?y[i];??
  • }??

  • [cpp]?view plaincopyprint?
  • //?multvec.c??
  • void?multvec(int*x,?int*?y,?int*??z,?int?n)??
  • {??
  • ?????int?i?=?0;??
  • ?????for(;?i?<?n;?++i)??
  • ??????????z[i]?=?x[i]?*?y[i];??
  • }??


  • 使用AR工具創(chuàng)建靜態(tài)庫文件: 為了使用這個(gè)庫,編寫一個(gè)應(yīng)用(其調(diào)用addvec庫中的函數(shù)): [cpp]?view plaincopyprint?
  • /*?main2.c?*/??
  • #include?<stdio.h>??
  • ??
  • int?x[2]?=?{1,?2};??
  • int?y[2]?=?{3,?4};??
  • int?z[2]={0};??
  • ??
  • int?main()??
  • {??
  • ????addvec(x,?y,?z,?2);??
  • ????printf("z?=?[%d?%d]\n",?z[0],?z[1]);??
  • ????return?0;??
  • }??


  • 編譯-鏈接-運(yùn)行程序: 注1-static 參數(shù)告訴編譯器驅(qū)動程序,鏈接器應(yīng)該構(gòu)建一個(gè)完全的可執(zhí)行目標(biāo)文件,它可以加載到存儲器并運(yùn)行,在加載時(shí)無需進(jìn)一步的鏈接 -即一次性靜態(tài)鏈接完畢,不允許存在動態(tài)鏈接注2:當(dāng)鏈接器運(yùn)行時(shí),它判定addvec.o定義的addvec符號是被main2.o引用的,所以它拷貝addvec.o到可執(zhí)行文件。因?yàn)槌绦蛑袥]有引用任何由multvec.o定義的符號,所以鏈接器就不會拷貝這個(gè)模塊到可執(zhí)行文件。同時(shí),鏈接器還會拷貝libc.a中的pirintf.o模塊,以及許多C運(yùn)行時(shí)系統(tǒng)中的其他模塊。鏈接器完整的行為可如下圖所示: 二、共享庫 1、概念:共享庫是一個(gè)目標(biāo)模塊(以.so后綴表示),在運(yùn)行時(shí),可以加載到任意的存儲器地址,并和一個(gè)在存儲器中的程序鏈接起來,這個(gè)過程稱為動態(tài)鏈接,是由一個(gè)叫做動態(tài)鏈接器的程序來執(zhí)行的。 2、分類:根據(jù)加載和鏈接共享庫的時(shí)機(jī)又可分為:A)應(yīng)用程序自身加載時(shí)動態(tài)鏈接和加載共享庫;B)應(yīng)用程序運(yùn)行過程中動態(tài)鏈接和加載共享庫兩種情況。 2-A:應(yīng)用程序自身加載時(shí)動態(tài)鏈接和加載共享庫 2-A.1 基本思路是:當(dāng)創(chuàng)建可執(zhí)行文件時(shí),靜態(tài)執(zhí)行一些鏈接(共享庫的重定位和符號表信息,而非代碼和數(shù)據(jù)),然后在應(yīng)用程序加載時(shí),動態(tài)完成鏈接過程。 2-A.2 創(chuàng)建與應(yīng)用 創(chuàng)建類似于靜態(tài)庫的創(chuàng)建,假設(shè)我們現(xiàn)在想在一個(gè)叫做libvector.so的共享庫庫中提供以下addvec和multvec函數(shù): 下面使用-shared選項(xiàng)來指示鏈接器創(chuàng)建一個(gè)共享的目標(biāo)文件(即共享庫),鏈接并運(yùn)行程序: ? 注1-fPIC選項(xiàng)指示編譯器生成與位置無關(guān)的代碼 其動態(tài)鏈接過程可如下圖所示: 注2:在可執(zhí)行文件p2中沒有拷貝任何libvector.so真正的代碼和數(shù)據(jù)節(jié),而是由鏈接器拷貝了一些重定位和符號表信息,它們使得運(yùn)行時(shí)動態(tài)鏈接器可以解析libvector.so中代碼和數(shù)據(jù)的引用,重定位完成鏈接任務(wù)。其中需要重定位的有:
    • 1)重定位libc.so的文本和數(shù)據(jù)到某個(gè)存儲器段;
    • 2)重定位libvector.so的文本和數(shù)據(jù)到另一個(gè)存儲器段;
    • 3)重定位p2中所有對libc.so和libvector.so定義的符號的引用。
    最后鏈接器將控制傳遞給應(yīng)用程序。從這個(gè)時(shí)刻開始,共享庫的位置就固定了,并在在程序的執(zhí)行過程中都不會再改變2-B:應(yīng)用程序運(yùn)行過程中動態(tài)鏈接和加載共享庫 2-B.1 概念:與A情況不同,此情況下:應(yīng)用程序在運(yùn)行過程中要求動態(tài)鏈接器加載和鏈接任意共享庫,而無需編譯時(shí)鏈接那些庫到應(yīng)用中。 2-B.2 應(yīng)用實(shí)例 Linux系統(tǒng)為應(yīng)用程序在運(yùn)行過程中加載和鏈接共享庫提供了一組API: [cpp]?view plaincopyprint?
  • #include<dlfcn.h>??
  • ??
  • /*?加載和鏈接共享庫?filename?
  • ????filename:共享庫的名字?
  • ????flag有:RTLD_LAZY,?RTLD_NOW,二者均可以和RTLD_GLOBAL表示取或?
  • */??
  • void?*dlopen(const?char?*filename,?int?flag);?//?若成功則返回執(zhí)行句柄的指針,否則返回NULL??
  • ??
  • /*根據(jù)共享庫操作句柄與符號,返回符號對應(yīng)的地址?
  • ????handle:共享庫操作句柄?
  • ????symbol:需要引用的符號名字?
  • */??
  • void?*dlsym(void?*handle,?char?*symbol);?//?若成功則返回執(zhí)行符號的指針(即地址),若出錯(cuò)則返回NULL??
  • ??
  • /*?如果沒有程序正在使用這個(gè)共享庫,卸載該共享庫?*/??
  • int?dlclose(void?*handle);?//?若卸載成功,則返回0,否則返回-1??
  • ??
  • /*?捕捉最近發(fā)生的錯(cuò)誤?*/??
  • const?char?*dlerror(void);?//?若前面對dlopen,dlsym或dlclose調(diào)用失敗,則返回錯(cuò)誤消息,否則返回NULL??


  • ?

    例子

    ?

    [cpp]?view plaincopyprint?
  • #include?<stdio.h>??
  • #include?<stdlib.h>??
  • #include?<dlfcn.h>??
  • ??
  • int?x[2]?=?{1,?2};??
  • int?y[2]?=?{3,?4};??
  • int?z[2]?={0};??
  • ??
  • int?main()??
  • {??
  • ????void?*handle;??
  • ????void?(*addvec)(int?*,?int?*,?int?*,int);??
  • ????char?*error;??
  • ??
  • ????handle?=?dlopen("./libvector.so",?RTLD_LAZY);??
  • ????if(!handle){??
  • ????????fprintf(stderr,?"%s\n",?dlerror());??
  • ????????exit(1);??
  • ????}??
  • ??
  • ????addvec?=?dlsym(handle,?"addvec");??
  • ????if((error?=?dlerror())?!=?NULL){??
  • ????????fprintf(stderr,?"%s\n",?dlerror());??
  • ????????exit(1);??
  • ????}??
  • ??
  • ????addvec(x,?y,?z,?2);??
  • ????printf("z?=?[%d?%d]\n",?z[0],?z[1]);??
  • ??
  • ????if(dlclose(handle)?<?0){??
  • ????????fprintf(stderr,?"%s\n",?dlerror());??
  • ????????exit(1);??
  • ????}??
  • ??
  • ????return?0;??
  • }??

  • 運(yùn)行結(jié)果:-ldl參數(shù):表示生成的對象模塊需要用到共享庫

    ?

    ?

    Referebces:

    ?

    1.《深入理解計(jì)算機(jī)系統(tǒng)》第7章:鏈接 P448-P479

    2.?靜態(tài)庫、共享庫、動態(tài)庫的創(chuàng)建和使用 :http://bbs.chinaunix.net/thread-2037617-1-1.html

    3.?Linux 動態(tài)庫剖析:http://www.ibm.com/developerworks/cn/linux/l-dynamic-libraries/

    4.?dlopen:?http://baike.baidu.com/link?url=VswI42A-IxFuF5SelbJxDREXuY0BvYWHEdcCYozSNH93ark0nTMi4YdhHrvt-bIo2_F-swU2onuYMNwXeUGVMq

    總結(jié)

    以上是生活随笔為你收集整理的【转】Linux 静态库与共享库的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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