Linux 中的动态链接库和静态链接库是干什么的?
link
什么是庫?
庫是寫好的現(xiàn)有的,成熟的,可以復用的代碼。現(xiàn)實中每個程序都要依賴很多基礎(chǔ)的底層庫,不可能每個人的代碼都從零開始,因此庫的存在意義非同尋常。
本質(zhì)上來說庫是一種可執(zhí)行代碼的二進制形式,可以被操作系統(tǒng)載入內(nèi)存執(zhí)行。庫有兩種:靜態(tài)庫(.a、.lib)和動態(tài)庫(.so、.dll)。 windows上對應(yīng)的是.lib .dll linux上對應(yīng)的是.a .so
在這里先介紹下Linux下的gcc編譯的幾個選項
g++ -c hellospeak.cpp會將hellospeak.cpp 選項 -c 用來告訴編譯器編譯源代碼但不要執(zhí)行鏈接,輸出結(jié)果為對象文件。文件默認名與源碼文件名相同,只是將其后綴變?yōu)?.o。例如,上面的命令將編譯源碼文件hellospeak.cpp 并生成對象文件 hellospeak.o;下面這條命令將上述兩個源碼文件編譯鏈接成一個單一的可執(zhí)行程序:
g++ hellospeak.cpp speak.cpp -o hellospeak如果沒有-o和后面的參數(shù),編譯器采用默認的 a.out
本例中就會生成hellospeak 這樣的可執(zhí)行程序
所謂靜態(tài)、動態(tài)是指鏈接。回顧一下,將一個程序編譯成可執(zhí)行程序的步驟:
圖:編譯過程
靜態(tài)庫
之所以成為【靜態(tài)庫】,是因為在鏈接階段,會將匯編生成的目標文件.o與引用到的庫一起鏈接打包到可執(zhí)行文件中。因此對應(yīng)的鏈接方式稱為靜態(tài)鏈接。
試想一下,靜態(tài)庫與匯編生成的目標文件一起鏈接為可執(zhí)行文件,那么靜態(tài)庫必定跟.o文件格式相似。其實一個靜態(tài)庫可以簡單看成是一組目標文件(.o/.obj文件)的集合,即很多目標文件經(jīng)過壓縮打包后形成的一個文件。靜態(tài)庫特點總結(jié):
l 靜態(tài)庫對函數(shù)庫的鏈接是放在編譯時期完成的。
l 程序在運行時與函數(shù)庫再無瓜葛,移植方便。
l 浪費空間和資源,因為所有相關(guān)的目標文件與牽涉到的函數(shù)庫被鏈接合成一個可執(zhí)行文件。
Linux下創(chuàng)建與使用靜態(tài)庫
Linux靜態(tài)庫命名規(guī)則
Linux靜態(tài)庫命名規(guī)范,必須是"lib[your_library_name].a":lib為前綴,中間是靜態(tài)庫名,擴展名為.a。
創(chuàng)建靜態(tài)庫(.a)
通過上面的流程可以知道,Linux創(chuàng)建靜態(tài)庫過程如下:
l 首先,將代碼文件編譯成目標文件.o(StaticMath.o)
g++ -c StaticMath.cpp注意帶參數(shù)-c,否則直接編譯為可執(zhí)行文件
l 然后,通過ar工具將目標文件打包成.a靜態(tài)庫文件
ar -crv libstaticmath.a StaticMath.o
生成靜態(tài)庫libstaticmath.a。
-------------------------------分割線------------------------
-------------------------------分割線------------------------
動態(tài)庫
通過上面的介紹發(fā)現(xiàn)靜態(tài)庫,容易使用和理解,也達到了代碼復用的目的,那為什么還需要動態(tài)庫呢?
為什么還需要動態(tài)庫?
為什么需要動態(tài)庫,其實也是靜態(tài)庫的特點導致。
l 空間浪費是靜態(tài)庫的一個問題。
另一個問題是靜態(tài)庫對程序的更新、部署和發(fā)布頁會帶來麻煩。如果靜態(tài)庫liba.lib更新了,所以使用它的應(yīng)用程序都需要重新編譯、發(fā)布給用戶(對于玩家來說,可能是一個很小的改動,卻導致整個程序重新下載,全量更新)。
動態(tài)庫在程序編譯時并不會被連接到目標代碼中,而是在程序運行是才被載入。不同的應(yīng)用程序如果調(diào)用相同的庫,那么在內(nèi)存里只需要有一份該共享庫的實例,規(guī)避了空間浪費問題。動態(tài)庫在程序運行是才被載入,也解決了靜態(tài)庫對程序的更新、部署和發(fā)布頁會帶來麻煩。用戶只需要更新動態(tài)庫即可,增量更新。
動態(tài)庫特點總結(jié):
l 動態(tài)庫把對一些庫函數(shù)的鏈接載入推遲到程序運行的時期。
l 可以實現(xiàn)進程之間的資源共享。(因此動態(tài)庫也稱為共享庫)
l 將一些程序升級變得簡單。
l 甚至可以真正做到鏈接載入完全由程序員在程序代碼中控制(顯示調(diào)用)。
Window與Linux執(zhí)行文件格式不同,在創(chuàng)建動態(tài)庫的時候有一些差異。
l 在Windows系統(tǒng)下的執(zhí)行文件格式是PE格式,動態(tài)庫需要一個DllMain函數(shù)做出初始化的入口,通常在導出函數(shù)的聲明時需要有_declspec(dllexport)關(guān)鍵字。
l Linux下gcc編譯的執(zhí)行文件默認是ELF格式,不需要初始化入口,亦不需要函數(shù)做特別的聲明,編寫比較方便。
與創(chuàng)建靜態(tài)庫不同的是,不需要打包工具(ar、lib.exe),直接使用編譯器即可創(chuàng)建動態(tài)庫
總結(jié)
以上是生活随笔為你收集整理的Linux 中的动态链接库和静态链接库是干什么的?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux可执行文件如何装载进虚拟内存
- 下一篇: Linux 下的动态链接库问题