Linux C編程(四) 之 靜態庫和動態庫

概述

linux下有兩種庫:動態庫和靜態庫 二者的不同點在於代碼被載入的時刻不同。
靜態庫的代碼在編譯過程中已經被載入可執行程序,因此體積比較大。
動態庫(共享庫)的代碼在可執行程序運行時才載入內存,在編譯過程中僅簡單的引用,因此代碼體積比較小。
不同的應用程序如果調用相同的庫,那麼在內存中只需要有一份該動態庫(共享庫)的實例。
靜態庫和動態庫的最大區別,靜態情況下,把庫直接加載到程序中,而動態庫鏈接的時候,它只是保留接口,將動態庫與程序代碼獨立,這樣就可以提高代碼的可複用度,和降低程序的耦合度。
靜態庫在程序編譯時會被複制到目標代碼中,程序運行時將不再需要該靜態庫。
動態庫在程序編譯時並不會被複制到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態庫存在

  1. 靜態庫的編寫和使用

     命名規則:lib庫名.a
    
    1. 將所有要加入靜態庫的模塊編譯爲目標文件.

       juggler@ubuntu:~/uc/day03/t_math$ ls
       add.c  main.c  mul.c  p_math.h
       juggler@ubuntu:~/uc/day03/t_math$ gcc -c add.c mul.c tarena@ubuntu:~/uc/day03/t_math$ ls
       add.c  add.o  main.c  mul.c  mul.o  p_math.h
      
    2. 將第一步生成的目標文件打包到靜態庫文件中

       juggler@ubuntu:~/uc/day03/t_math$ ar -r libpmath.a *.o
       ar: 正在創建 libpmath.a
       juggler@ubuntu:~/uc/day03/t_math$ ls 
       add.c  libpmath.a  mul.c  p_math.h
       add.o  main.c      mul.o
      
    3. 使用靜態庫文件鏈接生成可執行文件

       juggler@ubuntu:~/uc/day03/t_math$ gcc -c main.c 
       juggler@ubuntu:~/uc/day03/t_math$ gcc main.o -L. -lpmath
       juggler@ubuntu:~/uc/day03/t_math$ ls
       add.c  a.out       main.c  mul.c  p_math.h
       add.o  libpmath.a  main.o  mul.o
       juggler@ubuntu:~/uc/day03/t_math$ ./a.out 
       6+2=8
       -L路徑    鏈接器尋找庫文件的路徑
       -l庫名    指定要找的庫的名字
       -I 路徑   預處理時尋找頭文件的路徑
      
  • 在UNIX中,使用ar命令創建或者操作靜態庫

      ar archivefile objfile
      
      archivefile:archivefile是靜態庫的名稱
      
      objfile:objfile是已.o爲擴展名的中間目標文件名,可以多個並列
      
      參數 意義
      
      -r 將objfile文件插入靜態庫尾或者替換靜態庫中同名文件
      
      -x 從靜態庫文件中抽取文件objfile
      
      -t 打印靜態庫的成員文件列表
      
      -d 從靜態庫中刪除文件objfile
      
      -s 重置靜態庫文件索引
      
      -v 創建文件冗餘信息
      
      -c 創建靜態庫文件
    
  1. 動態鏈接
    1. 動態鏈接庫的製作和使用

       * 命名規則 lib庫名.so
      
    2. 將要加入動態庫的源文件編譯爲目標文件(與位置無關的目標文件)

       t_math$ls
       add.c  main.c  mul.c  p_math.h
       t_math$gcc -c -fPIC add.c mul.c 
       t_math$ls
       add.c  add.o  main.c  mul.c  mul.o  p_math.h
      
       -fPIC:生成與位置無關的目標文件
      
    3. 將第一步生成的目標文件打包到動態庫文件中

       t_math$gcc -shared -o libpmath.so *.o
       t_math$ls 
       add.c  libpmath.so  mul.c  p_math.h
       add.o  main.c       mul.o
      
    4. 使用動態庫鏈接生成可執行文件

       t_math$gcc main.c -L. -lpmath
       t_math$ls
       add.c  a.out        main.c  mul.o
       add.o  libpmath.so  mul.c   p_math.h
       
       t_math$a.out 
       a.out: error while loading shared libraries: libpmath.so: cannot open shared object file: No such file or directory
      
    5. 使用靜態庫鏈接生成的可執行文件.從靜態庫中找到程序中使用的模塊,將這些模塊合併到可執行文件中.可執行文件是獨立的文件.不再依賴靜態庫文件.

    6. 使用動態庫生成的可執行文件.和動態庫是兩個獨立的模塊.這種可執行文件要執行的時候,必須將可執行文件和動態庫一起加載到內存.

    7. 需要指到可執行文件依賴哪些動態庫文件?
      ldd a.out

    8. 告訴動態鏈接器到哪裏去找動態庫文件.
      兩種方法解決

      1. 使用LD_LIBRARY_PATH環境變量告訴動態鏈接器

         export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
        
      2. 鏈接器默認的搜索路徑是/lib或者/usr/lib

         mv libpmath.so /lib
         mv libpmath.so /usr/lib
        
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章