天天看點

靜态庫與共享庫靜态庫與共享庫

靜态庫與共享庫

  • “程式庫”包含了資料和可執行代碼的檔案,其不能單獨執行,可以作為其它執行程式的一部分來完成某些功能。庫的存在,可以使得程式子產品化,可以加快程式的再編譯,可以實作代碼重用,可以使得程式便于更新,同時也保證了代碼的保密性。程式庫可分靜态庫(static library)和共享庫(shared object)。
  • 靜态庫是在可執行程式運作前就已經加入到執行碼中,成為執行程式的一部分。共享庫,是在執行程式啟動時加載到執行程式中,可以被多個執行程式共享使用。
  • 靜态庫在應用程式生成時,可以不必再編譯,節省再編譯時間。但在編譯器越來越快的今天,這一點似乎已不重要。如果其他開發人員要使用你的程式,而你又不想給其源碼,提供靜态庫是一種選擇。從理論上講,應用程式使用了靜态庫,要比使用動态加載庫速度快1-5%,但實際上可能并非如此。由此看來,除了使用友善外,靜态庫可能并非一種好的選擇。
  • 共享庫比較明顯的優勢在于庫是獨立的,便于維護和更新;同時共享庫節約程式的記憶體,可以避免相同代碼 加載到程式中是的程式過大。
靜态庫與共享庫靜态庫與共享庫

靜态庫

靜态庫可以認為是一些目标代碼的集合。按照習慣,一般以“.a”做為檔案字尾名。使

用ar(archiver)指令可以建立靜态庫。

  • 首先把要加入靜态庫的檔案生成.o檔案
    gcc -c add.c sub.c mul.c dive.c
  • 再通過ar rcs指令生成靜态庫,靜态庫以lib開頭命名
ar rcs libmycalc.a add.o sub.o mul.o dive.o
  • 靜态庫建立成功後,需要連結到應用程式中使用。使用gcc的-l選項來指定靜态庫,使用-L參數來指定庫檔案的搜尋路徑。比如上述例子應指定-lmylib,所有庫檔案名都以lib開頭,開頭的lib在指定參數時應省略。-l和-L之後都直接帶參數而不跟空格。
gcc -Iinclude/ test.c -lmycalc -Llib/ -o app

動态庫

  • 首先使用-fPIC或-fpic生成與代碼無關的.o檔案。
    gcc -c -fPIC add.c sub.c mul.c dive.c
  • 再使用.o檔案生成共享庫
    gcc -shared -Wl,soname,libmycalc.so.1 -o libmycalc.so.1.0.1 add.o sub.o mul.o dive.o
  • 在啟動一個ELF二進制執行程式時,一個特殊的程式“程式裝載器”會被自動裝載并運作。在linux中,這個程式裝載器就是/lib/ld-linux.so.X(X是版本号)。它會查找并裝載應用程式所依賴的所有共享庫。被搜尋的目錄儲存在/etc/ld.so.conf檔案中。

sudo vim /etc/ld.so.conf

加上共享庫的路徑

  • 更新查找共享庫的路徑
    sudo ldconfig -v
  • 手動添加link nam
    ln -s libmycal.so.1.0.1 libmycal.so
  • 按照共享庫的命名慣例,每個共享庫有三個檔案名:real name、soname和linker name。真正的庫檔案(而不是符号連結)的名字是real name,包含完整的共享庫版本号。soname是一個符号連結的名字,隻包含共享庫的主版本号,主版本号一緻即可保證庫函數的接口一緻,是以應用程式的.dynamic段隻記錄共享庫soname,隻要soname一緻,這個共享庫就可以用。如libmyab.so.1和libmyab.so.2是兩個主版本号不同的libmyab,有些應用程式依賴于libmyab.so.1,有些應用程式依賴于libmyab.so.2,但對于依賴libmyab.so.1的應用程式來說,真正的庫檔案不管libmyab.so.1.10還是libmyab.so.1.11都可以用,是以使用共享庫可以很友善地更新庫檔案而不需要重新編譯應用程式,這是靜态庫所沒有的優點。注意libc的版本編号有一點特殊,libc-2.8.90.so的主版本号是6而不是2或2.8。linker name僅在編譯連結時使用,gcc的-L選項應該指定linker name所在的目錄。有的linker name是庫檔案的一個符号連結,有的linker name是一段連結腳本。例如上面的libc.so就是一個linker name,它是一段連結腳本

繼續閱讀