include的header檔案,鏈結資料庫,系統定義,總共有下列**指定gcc去那找。
當初在編譯時指定的(在~gcc/gcc/collect2.c:locatelib()
寫在specs內的
後來用-d -i -l指定的
gcc環境變數設定(編譯的時候)
ld.so的環境變數(這是run time的時候)
一、標頭檔案
gcc 在編譯時如何去尋找所需要的標頭檔案 :
※所以header file的搜尋會從-i開始
※然後找gcc的環境變數 c_include_path,cplus_include_path,objc_include_path
※再找內定目錄
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g -3
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include
庫檔案但是如果裝gcc的時候,是有給定的prefix的話,那麼就是
/usr/include
prefix/include
prefix/***-***-***-gnulibc/include
prefix/lib/gcc-lib/***x-***-***-gnulibc/2.8.1/include
二、庫檔案
cos()等函式庫的選項要多加 -lm
編譯的時候:
※gcc會去找-l
※再找gcc的環境變數library_path
※再找內定目錄 /lib /usr/lib /usr/local/lib 這是當初compile gcc時寫在程式內的
三、執行時動態庫的搜尋路徑
1、在配置檔案/etc/ld.so.conf中指定動態庫搜尋路徑
2、通過環境變數ld_library_path指定動態庫搜尋路徑(當通過該環境變數指定多個動態庫搜尋路徑時,路徑之間用冒號":"分隔)
3、在編譯目標**時指定該程式的動態庫搜尋路徑(還可以在編譯目標**時指定程式的動態庫搜尋路徑。
這是通過gcc 的引數"-wl,-rpath,"指定(如例3所示)。當指定多個動態庫搜尋路徑時,路徑之間用冒號":"分隔)
4、預設的動態庫搜尋路徑/lib
5、預設的動態庫搜尋路徑/usr/lib
可以通過執行可執行檔案pos得到的結果不同獲知其搜尋到了哪個動態庫,從而獲得第1個動態庫搜尋順序,然後刪除該動態庫,
再執行程式pos,獲得第2個動態庫搜尋路徑,再刪除第2個被搜尋到的動態庫,
如此往復,將可得到linux搜尋動態庫的先後順序。
程式pos執行的輸出結果和搜尋到的動態庫的對應關係如表1所示
程式pos輸出結果 使用的動態庫 對應的動態庫搜尋路徑指定方式
./ ./libpos.so 編譯目標**時指定的動態庫搜尋路徑
/root/test/env/lib /root/test/env/lib/libpos.so 環境變數ld_library_path指定的動態庫搜尋路徑
/root/test/conf/lib /root/test/conf/lib/libpos.so 配置檔案/etc/ld.so.conf中指定的動態庫搜尋路徑
/lib /lib/libpos.so 預設的動態庫搜尋路徑/lib
/usr/lib /usr/lib/libpos.so 預設的動態庫搜尋路徑/usr/lib
綜合以上結果可知,動態庫的搜尋路徑搜尋的先後順序是:
1.編譯目標**時指定的動態庫搜尋路徑;
2.環境變數ld_library_path指定的動態庫搜尋路徑;
3.配置檔案/etc/ld.so.conf中指定的動態庫搜尋路徑;
4.預設的動態庫搜尋路徑/lib;
5.預設的動態庫搜尋路徑/usr/lib。
[1]首先檢視 .dynamic 段是否包含了乙個叫dt_rpath的項(它是乙個以冒號分隔的庫檔案搜尋目錄列表)。這個項是在程式被聯結器連線時,由命令列開關或者環境變數新增上去的。它常應用於子系統中,比如像資料庫應用,我們要裝載一些程式集合以及支援庫到乙個目錄中去的時候。
[2]檢視是否存在環境變數 ld_library_path(它是乙個以冒號分隔的庫檔案搜尋目錄列表)。這個項可以幫助開發者建立乙個新版本的庫,把他的路徑新增到ld_library_path中,把它和現存的可連線程式一同使用,用來測試新的庫,
[3]聯結器檢視庫快取記憶體檔案 /etc/ld.so.conf ,它包含了庫名和路徑的乙個對應列表,如果庫名存在,聯結器就使用它對應的路徑,用這個查詢方法能夠找到大部分的庫(檔名不需要和要求完全符合,這點可以參考接下來的「庫的版本」)。
如果上敘的查詢都失敗,聯結器就查詢預設路徑 /usr/lib和/lib ,如果庫檔案依舊沒有找到,則顯示乙個錯誤然後退出。
聯結器找到了庫檔案後,先開啟它,然後讀取elf頭,找到指向各個段的指標。聯結器為庫的**段和資料段分配空間並對映到記憶體,隨後是bss(不分配空間)。.通過庫的 .dynamic 段,聯結器新增這個庫的符號表到符號錶鏈,如果庫所依賴的其它庫沒有裝載的話,則新增那個庫到裝載佇列中。
編譯程式時如果程式依賴的動態鏈結庫沒有安裝在系統標準路徑:/lib/或/usr/lib程式執行時往往提示找不到相應的動態鏈結庫檔案無法執行,原因就在於動態鏈結載入器ld的搜尋路徑列表裡沒有你的庫安裝路徑。
1.編譯目標**時指定的動態庫搜尋路徑;
(1)在編譯時通過gcc 的引數"-wl,-rpath,"指定。當指定多個動態庫搜尋路徑時,路徑之間用冒號":"分隔。(2)用編譯選項-l來指定動態鏈結庫所在的目錄(供編譯器查詢用),同時用-l選項指定縮寫的動態鏈結庫名。
這兩者之間的區別:
2.環境變數ld_library_path指定的動態庫搜尋路徑;
3.配置檔案/etc/ld.so.conf中指定的動態庫搜尋路徑;
/etc/ld.so.conf的第一行有個引用命令:include ld.so.conf.d/*.conf
因此,最優雅的方式是在ld.so.conf.d目錄下建立乙個你的程式依賴的配置檔案,配置檔案內容為程式依賴的動態鏈結庫的路徑,乙個路徑一行。
新增完配置檔案後執行ldconfig使其生效。
4.預設的動態庫搜尋路徑/lib;
5.預設的動態庫搜尋路徑/usr/lib;
我們可以採用以下三種方法來共享動態鏈結庫:(注:均須在超級使用者狀態下操作,以我的動態鏈結庫libmy.so共享過程為例)
(1)拷貝動態鏈結庫到系統共享目錄下,或在系統共享目錄下為該動態鏈結庫建立個連線(硬連線或符號連線均可,常用符號連線).這裡說的系統共享目錄,指的是linux動態鏈結庫存放的目錄,它包含/lib,/usr/lib以及/etc/ld.so.conf檔案內所列的一系列目錄.
# cp libmy.so /lib
# ldconfig#或:
# ln -s `pwd`/libmy.so /lib
# ldconfig
#(2)將動態鏈結庫所在目錄名追加到動態鏈結庫配置檔案/etc/ld.so.conf中.
# pwd >> /etc/ld.so.conf
# ldconfig
#(3)利用動態鏈結庫管理命令ldconfig,強制其搜尋指定目錄,並更新快取檔案,便於動態裝入.
# ldconfig `pwd`
#需要說明的是,這種操作方法雖然有效,但效果是暫時的,供程式測試還可以,一旦再度執行ldconfig,則快取檔案內容可能改變,所需的動態鏈結庫可能不被系統共享了.與之相比較,前兩種方法是可靠的方法,值得業已定型的動態鏈結庫共享時採用.前兩種方法還有乙個特點,即最後一條命令都是ldconfig,也即均需要更新一下快取檔案,以確保動態鏈結庫的共享生效.
檔案 標頭檔案 原始檔(C )
標頭檔案和原始檔中的函式宣告與定義 函式原型 file fsopen const char filename,const char mode,int shflag file wfsopen const wchar t filename,const wchar t mode,int shflag 注 ...
標頭檔案庫檔案
標頭檔案中有函式的申明,庫檔案實現函式的定義。比如,printf函式。使用時應包括stdio.h,開啟stdio.h你只能看到,printf這 個函式的申明,卻看不到printf具體是怎麼實現的,而函式的實現在相應的c庫 中。而庫檔案一般是以二進位制形式而不是c原始檔形式提供給使用者使用的。程式 中...
找不到標頭檔案 標頭檔案基礎講解(C語言)
在上linux課的時候被老師提了乙個問題,和 stdio.h 有什麼區別?老實說,當聽到這個問題的時候我心裡想這不是一樣的嗎?學和用了這麼久c語言竟然把這當成理想應當了。其實這些細節也很能體現基礎掌握得怎樣,聽說對於面試來說,大廠也比較傾向問這些基礎內功。和 stdio.h 的區別 當預處理器發現 ...