和luster學習在Linux建立庫函式(4)(轉)
和luster學習在Linux建立庫函式(4)(轉)[@more@]3.4. 建立一個共享函式庫
現在我們開始學習如何建立一個共享函式庫。其實建立一個共享函式庫非常容易。首先建立object檔案,這個檔案將加入透過gcc –fPIC 引數命令加入到共享函式庫裡面。PIC的意思是“位置無關程式碼”(Position Independent Code)。下面是一個標準的格式:
gcc -shared -Wl,-soname,your_soname -o library_name file_list library_list
下面再給一個例子,它建立兩個object檔案(a.o和b.o),然後建立一個包含a.o和b.o的共享函式庫。例子中”-g”和“-Wall”引數不是必須的。
gcc -fPIC -g -c -Wall a.cgcc -fPIC -g -c -Wall b.cgcc -shared -Wl,-soname,liblusterstuff.so.1 -o liblusterstuff.so.1.0.1 a.o b.o -lc
下面是一些需要注意的地方:
· 不用使用-fomit-frame-pointer這個編譯引數除非你不得不這樣。雖然使用了這個引數獲得的函式庫仍然可以使用,但是這使得除錯程式幾乎沒有用,無法跟蹤除錯。
· 使用-fPIC來產生程式碼,而不是-fpic。
· 某些情況下,使用gcc 來生成object檔案,需要使用“-Wl,-export-dynamic”這個選項引數。通常,動態函式庫的符號表裡面包含了這些動態的物件的符號。這個選項在建立ELF格式的檔案時候,會將所有的符號加入到動態符號表中。可以參考ld的幫助獲得更詳細的說明。
3.5. 安裝和使用共享函式庫
一旦你了一個共享函式庫,你還需要安裝它。其實簡單的方法就是複製你的庫檔案到指定的標準的目錄(例如/usr/lib),然後執行ldconfig。
如果你沒有許可權去做這件事情,例如你不能修改/usr/lib目錄,那麼你就只好透過修改你的環境變數來實現這些函式庫的使用了。首先,你需要建立這些共享函式庫;然後,設定一些必須得符號連結,特別是從soname到真正的函式庫檔案的符號連結,簡單的方法就是執行ldconfig:
ldconfig -n directory_with_shared_libraries
然後你就可以設定你的LD_LIBRARY_PATH這個環境變數,它是一個以逗號分隔的路徑的集合,這個可以用來指明共享函式庫的搜尋路徑。例如,使用bash,就可以這樣來
啟動一個程式my_program:
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH my_program
如果你需要的是過載部分函式,則你就需要建立一個包含需要過載的函式的object檔案,然後設定LD_PRELOAD環境變數。
通常你可以很方便的升級你的函式庫,如果某個API改變了,建立庫的程式會改變soname。然而,如果一個函式升級了某個函式庫而保持了原來的soname,你可以強行將老版本的函式庫複製到某個位置,然後重新命名這個檔案(例如使用原來的名字,然後後面加.orig字尾),然後建立一個小的“wrapper”指令碼來設定這個庫函式和相關的東西。例如下面的例子:
#!/bin/sh export LD_LIBRARY_PATH=/usr/local/my_lib:$LD_LIBRARY_PATH exec /usr/bin/my_program.orig $*
我們可以透過執行ldd來看某個程式使用的共享函式庫。例如你可以看ls這個實用工具使用的函式庫:
ldd /bin/ls
libtermcap.so.2 => /lib/libtermcap.so.2 (0x4001c000)
libc.so.6 => /lib/libc.so.6 (0x40020000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
通常我麼可以看到一個soname的列表,包括路徑。在所有的情況下,你都至少可以看到兩個庫:
· /lib/ld-linux.so.N(N是1或者更大,一般至少2)。這是這個用力載入其他所有的共享庫的庫。
· libc.so.N(N應該大於或者等於6)。這是C語言函式庫。
值得一提的是,不要在對你不信任的程式執行ldd命令。在ldd的manual裡面寫得很清楚,ldd是透過設定某些特殊的環境變數(例如,對於ELF物件,設定LD_TRACE_LOADED_OBJECTS),然後執行這個程式。這樣就有可能使得某地程式可能使得ldd來執行某些意想不到的程式碼,而產生不安全的隱患。
現在我們開始學習如何建立一個共享函式庫。其實建立一個共享函式庫非常容易。首先建立object檔案,這個檔案將加入透過gcc –fPIC 引數命令加入到共享函式庫裡面。PIC的意思是“位置無關程式碼”(Position Independent Code)。下面是一個標準的格式:
gcc -shared -Wl,-soname,your_soname -o library_name file_list library_list
下面再給一個例子,它建立兩個object檔案(a.o和b.o),然後建立一個包含a.o和b.o的共享函式庫。例子中”-g”和“-Wall”引數不是必須的。
gcc -fPIC -g -c -Wall a.cgcc -fPIC -g -c -Wall b.cgcc -shared -Wl,-soname,liblusterstuff.so.1 -o liblusterstuff.so.1.0.1 a.o b.o -lc
下面是一些需要注意的地方:
· 不用使用-fomit-frame-pointer這個編譯引數除非你不得不這樣。雖然使用了這個引數獲得的函式庫仍然可以使用,但是這使得除錯程式幾乎沒有用,無法跟蹤除錯。
· 使用-fPIC來產生程式碼,而不是-fpic。
· 某些情況下,使用gcc 來生成object檔案,需要使用“-Wl,-export-dynamic”這個選項引數。通常,動態函式庫的符號表裡面包含了這些動態的物件的符號。這個選項在建立ELF格式的檔案時候,會將所有的符號加入到動態符號表中。可以參考ld的幫助獲得更詳細的說明。
3.5. 安裝和使用共享函式庫
一旦你了一個共享函式庫,你還需要安裝它。其實簡單的方法就是複製你的庫檔案到指定的標準的目錄(例如/usr/lib),然後執行ldconfig。
如果你沒有許可權去做這件事情,例如你不能修改/usr/lib目錄,那麼你就只好透過修改你的環境變數來實現這些函式庫的使用了。首先,你需要建立這些共享函式庫;然後,設定一些必須得符號連結,特別是從soname到真正的函式庫檔案的符號連結,簡單的方法就是執行ldconfig:
ldconfig -n directory_with_shared_libraries
然後你就可以設定你的LD_LIBRARY_PATH這個環境變數,它是一個以逗號分隔的路徑的集合,這個可以用來指明共享函式庫的搜尋路徑。例如,使用bash,就可以這樣來
啟動一個程式my_program:
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH my_program
如果你需要的是過載部分函式,則你就需要建立一個包含需要過載的函式的object檔案,然後設定LD_PRELOAD環境變數。
通常你可以很方便的升級你的函式庫,如果某個API改變了,建立庫的程式會改變soname。然而,如果一個函式升級了某個函式庫而保持了原來的soname,你可以強行將老版本的函式庫複製到某個位置,然後重新命名這個檔案(例如使用原來的名字,然後後面加.orig字尾),然後建立一個小的“wrapper”指令碼來設定這個庫函式和相關的東西。例如下面的例子:
#!/bin/sh export LD_LIBRARY_PATH=/usr/local/my_lib:$LD_LIBRARY_PATH exec /usr/bin/my_program.orig $*
我們可以透過執行ldd來看某個程式使用的共享函式庫。例如你可以看ls這個實用工具使用的函式庫:
ldd /bin/ls
libtermcap.so.2 => /lib/libtermcap.so.2 (0x4001c000)
libc.so.6 => /lib/libc.so.6 (0x40020000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
通常我麼可以看到一個soname的列表,包括路徑。在所有的情況下,你都至少可以看到兩個庫:
· /lib/ld-linux.so.N(N是1或者更大,一般至少2)。這是這個用力載入其他所有的共享庫的庫。
· libc.so.N(N應該大於或者等於6)。這是C語言函式庫。
值得一提的是,不要在對你不信任的程式執行ldd命令。在ldd的manual裡面寫得很清楚,ldd是透過設定某些特殊的環境變數(例如,對於ELF物件,設定LD_TRACE_LOADED_OBJECTS),然後執行這個程式。這樣就有可能使得某地程式可能使得ldd來執行某些意想不到的程式碼,而產生不安全的隱患。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10796304/viewspace-962573/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 和luster學習在Linux建立庫函式(6)(轉)Linux函式
- 和luster學習在Linux建立庫函式(2)(轉)Linux函式
- 和luster學習在Linux建立庫函式(1)(轉)Linux函式
- 透過例子學習Lua(4)--函式的呼叫(轉)函式
- OpenCV學習筆記(4)——mixChannels函式OpenCV筆記函式
- Flutter學習筆記(4)--Dart函式Flutter筆記Dart函式
- 4、核心函式 (轉)函式
- 在Linux中建立靜態庫和動態庫Linux
- 函式學習函式
- 【Mysql 學習】日期函式函式MySql函式
- 字串函式庫的經典使用學習字串函式
- Js函式和物件學習體會JS函式物件
- mysql日期和時間函式學習MySql函式
- spark RDD的學習,filter函式的學習,split函式的學習SparkFilter函式
- GNU/linux的C函式庫介紹(轉)Linux函式
- 利用回撥函式和CSocket建立網路程式 (轉)函式
- MySQL函式學習(一)-----字串函式MySql函式字串
- 全面學習ORACLE Scheduler特性(4)建立和管理ScheduleOracle
- 轉 Lua標準庫: table函式, 數學函式, 字串函式/格式化/配對,函式字串
- 物聯網學習教程—函式引數和函式的值函式
- 函式學習五函式
- 函式學習六函式
- 函式學習三函式
- 函式學習四函式
- 函式學習二函式
- 函式的學習函式
- 學習Rust 函式Rust函式
- 學習dump函式函式
- ORACLE函式學習Oracle函式
- 輕鬆學習 JavaScript (4):函式中的 arguments 物件JavaScript函式物件
- FreeRTOS學習記錄--任務建立函式詳解函式
- C++初學解惑(4)——建構函式(上) (轉)C++函式
- c語言學習--time庫函式詳解C語言函式
- linux庫函式升級權威經驗(轉)Linux函式
- 初學Python(4)函式Python函式
- Linux程式建立函式vfork簡介Linux函式
- 【程式碼】--庫函式學習 ftp通訊 相關函式FTP
- 建立函式函式