linux靜態(tài)鏈接庫與動態(tài)鏈接庫的區(qū)別及動態(tài)庫的創(chuàng)建一、引言 通常情況下,對函數(shù)庫的鏈接是放在編譯時期(compile time)完成的。所有相關的對象文件(object file)與牽涉到的函數(shù)庫(library)被鏈接合成一個可執(zhí)行文件(executable file)。程序在運行時,與函數(shù)庫再無瓜葛,因為所有需要的函數(shù)已拷貝到自己門下。所以這些函數(shù)庫被成為靜態(tài)庫(static libaray),通常文件名為“libxxx.a”的形式。 其實,我們也可以把對一些庫函數(shù)的鏈接載入推遲到程序運行的時期(runtime)。這就是如雷貫耳的動態(tài)鏈接庫(dynamic link library)技術。 二、動態(tài)鏈接庫的特點與優(yōu)勢 首先讓我們來看一下,把庫函數(shù)推遲到程序運行時期載入的好處: 1. 可以實現(xiàn)進程之間的資源共享。 什么概念呢?就是說,某個程序的在運行中要調用某個動態(tài)鏈接庫函數(shù)的時候,操作系統(tǒng)首先會查看所有正在運行的程序,看在內存里是否已有此庫函數(shù)的拷貝了。如果有,則讓其共享那一個拷貝;只有沒有才鏈接載入。這樣的模式雖然會帶來一些“動態(tài)鏈接”額外的開銷,卻大大的節(jié)省了系統(tǒng)的內存資源。C的標準庫就是動態(tài)鏈接庫,也就是說系統(tǒng)中所有運行的程序共享著同一個C標準庫的代碼段。 2. 將一些程序升級變得簡單。用戶只需要升級動態(tài)鏈接庫,而無需重新編譯鏈接其他原有的代碼就可以完成整個程序的升級。Windows 就是一個很好的例子。 3. 甚至可以真正坐到鏈接載入完全由程序員在程序代碼中控制。 程序員在編寫程序的時候,可以明確的指明什么時候或者什么情況下,鏈接載入哪個動態(tài)鏈接庫函數(shù)。你可以有一個相當大的軟件,但每次運行的時候,由于不同的操作需求,只有一小部分程序被載入內存。所有的函數(shù)本著“有需求才調入”的原則,于是大大節(jié)省了系統(tǒng)資源。比如現(xiàn)在的軟件通常都能打開若干種不同類型的文件,這些讀寫操作通常都用動態(tài)鏈接庫來實現(xiàn)。在一次運行當中,一般只有一種類型的文件將會被打開。所以直到程序知道文件的類型以后再載入相應的讀寫函數(shù),而不是一開始就將所有的讀寫函數(shù)都載入,然后才發(fā)覺在整個程序中根本沒有用到它們。 三、動態(tài)鏈接庫的創(chuàng)建 由于動態(tài)鏈接庫函數(shù)的共享特性,它們不會被拷貝到可執(zhí)行文件中。在編譯的時候,編譯器只會做一些函數(shù)名之類的檢查。在程序運行的時候,被調用的動態(tài)鏈接庫 函數(shù)被安置在內存的某個地方,所有調用它的程序將指向這個代碼段。因此,這些代碼必須實用相對地址,而不是絕對地址。在編譯的時候,我們需要告訴編譯器, 這些對象文件是用來做動態(tài)鏈接庫的,所以要用地址不無關代碼(Position Independent Code (PIC))。 對gcc編譯器,只需添加上 -fPIC 標簽,如: gcc -fPIC -c file1.c gcc -fPIC -c file2.c gcc -shared libxxx.so file1.o file2.o 注意到最后一行,-shared 標簽告訴編譯器這是要建立動態(tài)鏈接庫。這與靜態(tài)鏈接庫的建立很不一樣,后者用的是 ar 命令。也注意到,動態(tài)鏈接庫的名字形式為 “libxxx.so” 后綴名為 “.so” 四、動態(tài)鏈接庫的使用 使用動態(tài)鏈接庫,首先需要在編譯期間讓編譯器檢查一些語法與定義。 這與靜態(tài)庫的實用基本一樣,用的是 -Lpath 和 -lxxx 標簽。如: gcc file1.o file2.o -Lpath -lxxx -o program.exe 編譯器會先在path文件夾下搜索libxxx.so文件,如果沒有找到,繼續(xù)搜索libxxx.a(靜態(tài)庫)。 在程序運行期間,也需要告訴系統(tǒng)去哪里找你的動態(tài)鏈接庫文件。在UNIX下是通過定義名為 LD_LIBRARY_PATH 的環(huán)境變量來實現(xiàn)的。只需將path賦值給此變量即可。csh 命令為: setenv LD_LIBRARY_PATH your/full/path/to/dll 一切安排妥當后,你可以用 ldd 命令檢查是否連接正常。 ldd program.exe
最主要的是GCC命令行的一個選項:
1、生成靜態(tài)庫 :庫名 libmylib.a ar rcs libmylib.a mylib.o 2、將靜態(tài)庫copy到 /usr/lib/ 或/lib/ 目錄下 cp libmylib.a /usr/lib/ 3、靜態(tài)庫的使用 比如測試文件為test.c gcc -0 test test.c -lmylib -l為選項, mylib為庫名。mylib為libmylib的中間部分,Linux下約定所有庫都以前綴lib開始 靜態(tài)庫以.a結尾,動態(tài)庫以.so結尾。再編譯程式時,無需帶上前綴和后綴。 注意:靜態(tài)庫的命名需要以"lib"開頭,否者連接是編譯器無法找到庫
|
|
|