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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

静态库和动态库的分析

發(fā)布時間:2023/12/9 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 静态库和动态库的分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?在Linux操作系統(tǒng)中,普遍使用ELF格式作為可執(zhí)行程序或者程序生成過程中的中間格式。ELF(Executable and Linking Format,可執(zhí)行連接格式)。

???? ELF文件格式包括三種主要的類型:可執(zhí)行文件、可重定向文件、共享庫:

1、可執(zhí)行文件(應用程序)
可執(zhí)行文件包含了代碼和數(shù)據(jù),是可以直接運行的程序。

2、可重定向文件(*.o)
可重定向文件又稱為目標文件,它包含了代碼和數(shù)據(jù)(這些數(shù)據(jù)是和其他重定位文件和共享的object文件一起連接時使用的)。
*.o文件參與程序的連接(創(chuàng)建一個程序)和程序的執(zhí)行(運行一個程序),它提供了一個方便有效的方法來用并行的視角看待文件的內(nèi)容,這些*.o文件的活動可以反映出不同的需要。
Linux下,我們可以用gcc -c編譯源文件時可將其編譯成*.o格式。

3、共享文件(*.so)
也稱為動態(tài)庫文件,它包含了代碼和數(shù)據(jù)(這些數(shù)據(jù)是在連接時候被連接器ld和運行時動態(tài)連接器使用的)。動態(tài)連接器可能稱為ld.so.1,libc.so.1或者 ld-linux.so.1。

那么到底什么是庫呢?

庫從本質(zhì)上來說是一種可執(zhí)行代碼的二進制格式,可以被載入內(nèi)存中執(zhí)行。庫分靜態(tài)庫動態(tài)庫兩種。二者的不同點在于代碼被載入的時刻不同。

靜態(tài)庫:這類庫的名字一般是libxxx.a,xxx為庫的名字。靜態(tài)庫在程序編譯時會被連接到目標代碼中,利用靜態(tài)函數(shù)庫編譯成的文件比較大,因為整個函數(shù)庫的所有數(shù)據(jù)都會被整合進目標代碼中,他的優(yōu)點就顯而易見了,即編譯后的執(zhí)行程序不需要外部的函數(shù)庫支持,因為所有使用的函數(shù)都已經(jīng)被編譯進去了。當然這也會成為他的缺點,因為如果靜態(tài)函數(shù)庫改變了,那么你的程序必須重新編譯。

動態(tài)庫:這類庫的名字一般是libxxx.M.N.so,同樣的xxx為庫的名字,M是庫的主版本號,N是庫的副版本號。當然也可以不要版本號,但名字必須有。相對于靜態(tài)函數(shù)庫,動態(tài)函數(shù)庫在編譯的時候并沒有被編譯進目標代碼中,你的程序執(zhí)行到相關(guān)函數(shù)時才調(diào)用該函數(shù)庫里的相應函數(shù),因此動態(tài)函數(shù)庫所產(chǎn)生的可執(zhí)行文件比較小。由于函數(shù)庫沒有被整合進你的程序,而是程序運行時動態(tài)的申請并調(diào)用,所以程序的運行環(huán)境中必須提供相應的庫。動態(tài)函數(shù)庫的改變并不影響你的程序,所以動態(tài)函數(shù)庫的升級比較方便。linux系統(tǒng)有幾個重要的目錄存放相應的函數(shù)庫,如/lib /usr/lib。

當要使用靜態(tài)的程序庫時,連接器會找出程序所需的函數(shù),然后將它們拷貝到執(zhí)行文件,由于這種拷貝是完整的,所以一旦連接成功,靜態(tài)程序庫也就不再需要了。然而,對動態(tài)庫而言,就不是這樣。動態(tài)庫會在執(zhí)行程序內(nèi)留下一個標記指明當程序執(zhí)行時,首先必須載入這個庫。由于動態(tài)庫節(jié)省空間,linux下進行連接的缺省操作是首先連接動態(tài)庫,也就是說,如果同時存在靜態(tài)和動態(tài)庫,不特別指定的話,將與動態(tài)庫相連接。

一、靜態(tài)庫

??????? 前面已經(jīng)介紹了靜態(tài)庫的概念,下面我們通過一個實例來看靜態(tài)庫的使用

1、生成靜態(tài)庫

1)這里準備了兩個庫的源碼st1 、st2用它們來制作庫libmytest.a,如下

[cpp]?view plaincopy
  • fs@ubuntu:~/qiang/stalib$?ls?-l??
  • total?12??
  • -rw-rw-r--?1?fs?fs?98?Jan??5?19:56?main.c??
  • -rw-rw-r--?1?fs?fs?69?Jan??5?19:55?st1.c??
  • -rw-rw-r--?1?fs?fs?68?Jan??5?19:55?st2.c??
  • fs@ubuntu:~/qiang/stalib$?cat?st1.c??
  • #include?<stdio.h>??
  • ??
  • void?print1()??
  • {??
  • ????printf("Hello!I?am?st1!\n?");??
  • }??
  • fs@ubuntu:~/qiang/stalib$?cat?st2.c??
  • #include?<stdio.h>??
  • ??
  • void?print2()??
  • {??
  • ????printf("Hello!I?am?st2!\n");??
  • }??
  • fs@ubuntu:~/qiang/stalib$?cat?main.c??
  • #include?<stdio.h>??
  • ??
  • int?main(int?argc,?const?char?*argv[])??
  • {??
  • ????print1();??
  • ????print2();??
  • ??????
  • ????return?0;??
  • }??
  • fs@ubuntu:~/qiang/stalib$???
  • 2) 生成libmytest.a文件

    創(chuàng)建靜態(tài)庫用ar命令,它將很多.o轉(zhuǎn)換成.a

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/stalib$?gcc?-c?st1.c?st2.c??
  • fs@ubuntu:~/qiang/stalib$?ar?crs?libmytest.a?st1.o?st2.o??
  • fs@ubuntu:~/qiang/stalib$?ls?-l??
  • total?24??
  • -rw-rw-r--?1?fs?fs?2262?Jan??5?20:04?libmytest.a??
  • -rw-rw-r--?1?fs?fs???98?Jan??5?19:56?main.c??
  • -rw-rw-r--?1?fs?fs???69?Jan??5?20:03?st1.c??
  • -rw-rw-r--?1?fs?fs?1024?Jan??5?20:04?st1.o??
  • -rw-rw-r--?1?fs?fs???69?Jan??5?20:03?st2.c??
  • -rw-rw-r--?1?fs?fs?1024?Jan??5?20:04?st2.o??
  • fs@ubuntu:~/qiang/stalib$?file?libmytest.a???
  • libmytest.a:?current?ar?archive??
  • fs@ubuntu:~/qiang/stalib$???
  • 靜態(tài)庫文件libmytest.a已經(jīng)生成,用file命令查看其屬性,發(fā)現(xiàn)它確實是歸檔壓縮文件。用ar -t libmytest.a可以查看一個靜態(tài)庫包含了那些obj文件:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/stalib$?ar?-t?libmytest.a???
  • st1.o??
  • st2.o??
  • fs@ubuntu:~/qiang/stalib$???
  • 2、使用靜態(tài)庫

    前面我們已經(jīng)寫好了main.c,現(xiàn)在測試一下

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/stalib$?gcc?-o?test?main.c?-L.?-lmytest??
  • fs@ubuntu:~/qiang/stalib$?ls?-l??
  • total?32??
  • -rw-rw-r--?1?fs?fs?2262?Jan??5?20:04?libmytest.a??
  • -rw-rw-r--?1?fs?fs???98?Jan??5?19:56?main.c??
  • -rw-rw-r--?1?fs?fs???69?Jan??5?20:03?st1.c??
  • -rw-rw-r--?1?fs?fs?1024?Jan??5?20:04?st1.o??
  • -rw-rw-r--?1?fs?fs???69?Jan??5?20:03?st2.c??
  • -rw-rw-r--?1?fs?fs?1024?Jan??5?20:04?st2.o??
  • -rwxrwxr-x?1?fs?fs?7248?Jan??5?20:07?test??
  • fs@ubuntu:~/qiang/stalib$?./test???
  • Hello!?I?am?st1!??
  • Hello!?I?am?st2!??
  • fs@ubuntu:~/qiang/stalib$???
  • 這里gcc的參數(shù)-L是告訴編譯器庫文件的路徑是當前目錄,-l是告訴編譯器要使用的庫的名字叫mytest。

    二、動態(tài)庫

    動態(tài)庫的基本概念
    1、動態(tài)鏈接庫是程序運行時加載的庫,當動態(tài)鏈接庫正確安裝后,所有的程序都可以使用動態(tài)庫來運行程序。動態(tài)鏈接庫是目標文件的集合,目標文件在動態(tài)鏈接庫中的組織方式是按照特殊方式形成的。庫中函數(shù)和變量的地址是相對地址,不是絕對地址,其真實地址在調(diào)用動態(tài)庫的程序加載時形成。

    2、動態(tài)鏈接庫的名稱有別名(soname), 真名(realname)和鏈接名(linker name)。別名由一個前綴lib,然后是庫的名字,再加上一個后綴“.so”構(gòu)成("libxxx.so")。真名是動態(tài)鏈接庫真實名稱,一般總是在別名的基礎加上一個小版本號,發(fā)布版本等構(gòu)成。除此之外,還有一個鏈接名,即程序鏈接時使用的庫的名字。

    3、在動態(tài)鏈接庫安裝的時候,總是復制文件到某個目錄下,然后用一個軟連接生成別名,在庫文件進行更新的時候,僅僅更新軟鏈接即可。

    下面我們通過一個實例來學習如何生成動態(tài)庫和使用動態(tài)庫

    1、生成動態(tài)庫

    1)當前文件夾下有下面四個文件

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?ls?-l??
  • total?16??
  • -rw-rw-r--?1?fs?fs?73?Jan??5?18:11?dy1.c??
  • -rw-rw-r--?1?fs?fs?74?Jan??5?18:11?dy2.c??
  • -rw-rw-r--?1?fs?fs?90?Jan??5?18:11?main.c??
  • -rw-rw-r--?1?fs?fs?95?Jan??5?18:10?mylib.h??
  • fs@ubuntu:~/qiang/lib/dylib$???
  • 文件內(nèi)容分別為:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?cat?mylib.h???
  • #ifndef?_MYLIB_H_??
  • #define?_MYLIB_H_??
  • ??
  • #include?<stdio.h>??
  • ??
  • void?print1();??
  • void?print2();??
  • ??
  • #endif??
  • fs@ubuntu:~/qiang/lib/dylib$?cat?dy1.c??
  • #include?"mylib.h"??
  • ??
  • void?print1()??
  • {??
  • ????printf("My?first?shared?lib!\n");??
  • }??
  • fs@ubuntu:~/qiang/lib/dylib$?cat?dy2.c??
  • #include?"mylib.h"??
  • ??
  • void?print2()??
  • {??
  • ????printf("My?second?shared?lib!\n");??
  • }??
  • fs@ubuntu:~/qiang/lib/dylib$?cat?main.c??
  • #include?"mylib.h"??
  • ??
  • int?main(int?argc,?char?*argv[])??
  • {??
  • ????print1();??
  • ????print2();??
  • ????return?0;??
  • }??
  • fs@ubuntu:~/qiang/lib/dylib$???
  • 2)這里我們將dy1.c與dy2.c用來創(chuàng)建動態(tài)庫

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?gcc?-fPIC?-Wall?-c?dy1.c?dy2.c??
  • fs@ubuntu:~/qiang/lib/dylib$?gcc?-shared?-o?libtest.so?dy1.o?dy2.o??
  • fs@ubuntu:~/qiang/lib/dylib$???
  • 這里 -fPIC 創(chuàng)建與地址無關(guān)的編譯程序,-shared指定生成動態(tài)鏈接庫。

    我們也可以一步到位

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?gcc?-o?libtest.so?-fPIC?-shared?dy1.c?dy2.c??
  • fs@ubuntu:~/qiang/lib/dylib$???
  • 我們可以看到下面已經(jīng)生成了一個libtest.so

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?ls?-l??
  • total?32??
  • -rw-rw-r--?1?fs?fs???73?Jan??5?18:11?dy1.c??
  • -rw-rw-r--?1?fs?fs?1332?Jan??5?18:29?dy1.o??
  • -rw-rw-r--?1?fs?fs???74?Jan??5?18:11?dy2.c??
  • -rw-rw-r--?1?fs?fs?1336?Jan??5?18:29?dy2.o??
  • -rwxrwxr-x?1?fs?fs?6798?Jan??5?18:29?libtest.so??
  • -rw-rw-r--?1?fs?fs???90?Jan??5?18:11?main.c??
  • -rw-rw-r--?1?fs?fs???95?Jan??5?18:10?mylib.h??
  • fs@ubuntu:~/qiang/lib/dylib$???
  • 2、使用動態(tài)鏈接庫
    ????? 在編譯程序時,使用動態(tài)鏈接庫和靜態(tài)庫是一致的,使用”-l庫名”的方式,在生成可執(zhí)行文件的時候會鏈接庫文件。使用如下命令:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?gcc?-o?test?main.c?-L.?-ltest??
  • fs@ubuntu:~/qiang/lib/dylib$?ls??
  • dy1.c??dy2.c??libtest.so??main.c??mylib.h??test??
  • 這里 -L 指定動態(tài)鏈接庫的路勁,-ldtest鏈接庫函數(shù)test 。-ltest是動態(tài)庫的調(diào)用規(guī)則。Linux系統(tǒng)下的動態(tài)庫命名方式是lib*.so,而在鏈接時表示位-l*,*是自己命名的庫名。
    我們可以看到這里已經(jīng)生成了test可執(zhí)行文件,我們可以執(zhí)行一下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?./test??
  • ./test:?error?while?loading?shared?libraries:?libtest.so:?cannot?open???
  • shared?object?file:?No?such?file?or?directory??
  • fs@ubuntu:~/qiang/lib/dylib$??
  • 可以發(fā)現(xiàn)發(fā)生了錯誤,這是因為程序運行時沒有找到動態(tài)鏈接庫造成的。程序編譯時鏈接動態(tài)庫和運行時使用動態(tài)鏈接庫的概念是不同的,在運行時,程序鏈接的動態(tài)鏈接庫需要在系統(tǒng)目錄下才行。

    這就到了動態(tài)庫的路徑問題,有三種方法:

    1)把庫拷貝到/usr/lib和/lib目錄下:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?sudo?cp?libtest.so?/lib??
  • [sudo]?password?for?fs:???
  • 這里要超級用戶權(quán)限sudo,我們看一下執(zhí)行結(jié)果:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?./test???
  • My?first?shared?lib!??
  • My?second?shared?lib!??
  • fs@ubuntu:~/qiang/lib/dylib$???
  • 這里執(zhí)行結(jié)果正確。

    2)在?LD_LIBRARY_PATH 環(huán)境變量中加上庫所在路徑

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?export?LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH??
  • fs@ubuntu:~/qiang/lib/dylib$???
  • 我們可以看到:libtest.so 的路徑已經(jīng)存在

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?ldd?test??
  • ????linux-gate.so.1?=>??(0xb774b000)??
  • ????libtest.so?=>?/home/fs/qiang/lib/dylib/libtest.so?(0xb7746000)??
  • ????libc.so.6?=>?/lib/i386-linux-gnu/libc.so.6?(0xb758d000)??
  • ????/lib/ld-linux.so.2?(0xb774c000)??
  • fs@ubuntu:~/qiang/lib/dylib$???
  • 我們可以看一下結(jié)果:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?./test???
  • My?first?shared?lib!??
  • My?second?shared?lib!??
  • fs@ubuntu:~/qiang/lib/dylib$???
  • 也能得到正確結(jié)果。

    3)添加/etc/ld.so.conf.d/*.conf文件。把庫所在的路徑加到文件末尾,并執(zhí)行l(wèi)dconfig刷新。

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/lib/dylib$?cd?/etc/ld.so.conf.d/??
  • fs@ubuntu:/etc/ld.so.conf.d$?ls??
  • i386-linux-gnu_GL.conf??libc.conf??
  • i686-linux-gnu.conf?????vmware-tools-libraries.conf??
  • fs@ubuntu:/etc/ld.so.conf.d$?sudo?vi?my.conf??
  • [sudo]?password?for?fs:???
  • fs@ubuntu:/etc/ld.so.conf.d$?cat?my.conf???
  • /home/fs/qiang/lib/dylib/libtest.so??
  • fs@ubuntu:/etc/ld.so.conf.d$???
  • 在/etc/ld.so.conf.d/下建立 my.conf? 里面只有一句/home/fs/qiang/lib/dylib/libtest.so 即libtest.so的路徑,然后執(zhí)行l(wèi)dconfig刷新即可。

    總結(jié)

    以上是生活随笔為你收集整理的静态库和动态库的分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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