Linux C開發 標頭檔案查詢 動態庫搜尋

2021-07-14 01:47:47 字數 4793 閱讀 3277

本文介紹在linux中標頭檔案的搜尋路徑,也就是說你通過include指定的標頭檔案,linux下的gcc編譯器它是怎麼找到它的呢。在此之前,先了解乙個基本概念。

標頭檔案是一種文字檔案,使用文字編輯器將**編寫好之後,以副檔名.h儲存就行了。標頭檔案中一般放一些重複使用的**,例如函式宣告、變數宣告、常數定義、巨集的定義等等。當使用#include語句將標頭檔案引用時,相當於將標頭檔案中所有內容,複製到#include處。#include有兩種寫法形式,分別是:

#include <> : 直接到系統指定的某些目錄中去找某些標頭檔案。

#include 「」 : 先到原始檔所在資料夾去找,然後再到系統指定的某些目錄中去找某些標頭檔案。

#include檔案可能會帶來乙個問題就是重複應用,如a.h引用的乙個函式是某種實現,而b.h引用的這個函式卻是另外一種實現,這樣在編譯的時候將會出現錯誤。所以,為了避免因為重複引用而導致的編譯錯誤,標頭檔案常具有:

#ifndef label

#define label

//**部分

#endif

的格式。其中label為乙個唯一的標號,命名規則跟變數的命名規則一樣。常根據它所在的頭檔名來命名,例如,如果標頭檔案的檔名叫做hardware.h,那麼可以這樣使用:

#ifndef __hardware_h__

#define __hardware_h__

//**部分

#endif

這樣寫的意思就是,如果沒有定義__hardware_h__,則定義__hardware_h__,並編譯下面的**部分,直到遇到#endif。這樣當重複引用時,由於__hardware_h__已經被定義,則下面的**部分就不會被編譯了,這樣就避免了重複定義。

一句話,標頭檔案事實上只是把一些常用的命令整合在裡面,你要用到哪方面的命令就載入哪個標頭檔案就可以了。

gcc尋找標頭檔案的路徑(按照1->2->3的順序)

1. 在gcc編譯原始檔的時候,通過引數-i指定標頭檔案的搜尋路徑,如果指定路徑有多個路徑時,則按照指定路徑的順序搜尋標頭檔案。命令形式如:「gcc -i /path/where/theheadfile/in sourcefile.c「,這裡原始檔的路徑可以是絕對路徑,也可以是相對路徑。eg:

設當前路徑為/root/test,include_test.c如果要包含標頭檔案「include/include_test.h「,有兩種方法:

1) include_test.c中#include 「include/include_test.h」或者#include "/root/test/include/include_test.h",然後gcc include_test.c即可

2) include_test.c中#include 或者#include ,然後gcc –i include include_test.c也可

2. 通過查詢gcc的環境變數c_include_path/cplus_include_path/objc_include_path來搜尋標頭檔案位置。

3. 再找內定目錄搜尋,分別是

/usr/include

/usr/local/include

/usr/lib/gcc-lib/i386-linux/2.95.2/include

最後一行是gcc程式的庫檔案位址,各個使用者的系統上可能不一樣。

gcc在預設情況下,都會指定到/usr/include資料夾尋找標頭檔案。

gcc還有乙個引數:-nostdinc,它使編譯器不再系統預設的頭檔案目錄裡面找標頭檔案,一般和-i聯合使用,明確限定標頭檔案的位置。在編譯驅動模組時,由於非凡的需求必須強制gcc不搜尋系統預設路徑,也就是不搜尋/usr/include要用引數-nostdinc,還要自己用-i引數來指定核心標頭檔案路徑,這個時候必須在makefile中指定。

4. 當#include使用相對路徑的時候,gcc最終會根據上面這些路徑,來最終構建出頭檔案的位置。如#include 就是包含檔案/usr/include/sys/types.h

1)elf可執行檔案中動態段中dt_rpath所指定的路徑。即在編譯目標**時, 對gcc加入鏈結引數「-wl,-rpath」指定動態庫搜尋路徑,eg:gcc -wl,-rpath,/home/arc/test,-rpath,/lib/,-rpath,/usr/lib/,-rpath,/usr/local/lib test.c

2)環境變數ld_library_path 指定的動態庫搜尋路徑

3)/etc/ld.so.cache中所快取的動態庫路徑,這個可以通過先修改配置檔案/etc/ld.so.conf中指定的動態庫搜尋路徑,然後執行ldconfig命令來改變。

4)預設的動態庫搜尋路徑/lib

5)預設的動態庫搜尋路徑/usr/lib

另外:在嵌入式linux系統的實際應用中,1和2被經常使用,也有一些相對簡單的的嵌入式系統會採用4或5的路徑來規範動態庫,3在嵌入式系統中使用的比較少, 因為有很多系統根本就不支援ld.so.cache。

那麼,動態鏈結器ld.so在這五種路徑中,是按照什麼樣的順序來搜尋需要的動態共享庫呢?答案這裡先告知就是按照上面的順序來得,即優先順序是:1-->2-->3-->4-->5。我們可以寫簡單的程式來證明這個結論。

首先,寫成5個函式,這5個函式名稱都叫pt,但是裡面的內容不一樣:

pt1.c

#include

void pt(){

printf("1 path on the gcc give \n");

pt2.c

#include

void pt(){

printf("2 path on the ld_library_path \n");

pt3.c

#include

void pt(){

printf("3 path on the /etc/ld.so.conf \n");

pt4.c

#include

void pt(){

printf("4 path on the /lib \n");

pt5.c

#include

void pt(){

printf("5 path on the /usr/lib \n");

然後,分別編譯這5個函式,然後將它們分別移到上面5種情況對應的5個不同目錄下:

gcc -fpic -c pt1.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /tmp/st/1/

gcc -fpic -c pt2.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /tmp/st/2/

gcc -fpic -c pt3.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /tmp/st/3/

gcc -fpic -c pt4.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /lib/

gcc -fpic -c pt5.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /usr/lib/

再次,編寫乙個main函式m,讓它來呼叫函式pt:

m.c

#include

int main(){

printf("start....\n");

pt();

printf("......end\n");

return 0;

最後,準備環境,讓ld都知道這5個路徑:

(a) 往/etc/ld.so.conf總增加一行,內容:/tmp/st/3,然後執行 ldconfig 命令

(b) export ld_library_path=/tmp/st/2

另外3中路徑,ld都可以得到,請接著看下面。

之後測試:

gcc m.c -o m1 -l/tmp/st/1 -lpt -wl,-rpath,/tmp/st/1

./m1

start....

1 path on the gcc give

......end

這裡在可執行檔案中動態段中dt_rpath所指定的路徑,因此需要在編譯m.c的時候就指定路徑,由於其他路徑都也告訴了ld,很明顯,此種方法優先順序最高了。

gcc m.c -o m -l/tmp/st/1 -lpt

./mstart....

2 path on the ld_library_path

......end

這裡很顯然呼叫了ld_library_path指定了路徑中的共享庫,因此此種情況優先順序第二。

mv /tmp/st/2/libpt.so /tmp/st/2/libpt2.so

/mstart....

3 path on the /etc/ld.so.conf

......end

這裡是呼叫了/etc/ld.so.cache中所快取的動態庫路徑中的共享庫,因此此種情況優先順序第三。

mv /tmp/st/3/libpt.so /tmp/st/3/libpt3.so

./mstart....

4 path on the /lib

......end

這裡是呼叫/lib中的共享庫,優先順序第四。

rm /lib/libpt.so

./mstart....

5 path on the /usr/lib

......end

這裡是呼叫/lib中的共享庫,優先順序第五。

故證明這五種路徑指定方法的優先順序是1-->2-->3-->4-->5!

Linux C 常用標頭檔案

sys types.h 資料型別定義 sys socket.h 提供socket函式及資料結構 netinet in.h 定義資料結構sockaddr in netdb.h 提供設定及獲取網域名稱的函式 sys ioctl.h 提供對i o控制的函式 sys poll.h 提供socket等待測試機...

Linux C常用的標頭檔案

原文出處 忘了 下的,只是在自己的文件找到 一些標頭檔案的作用 ansi c 提供斷言,assert 表示式 gcc。gtk,gnome 的基礎庫,提供很多有用的函式,如有資料結構操作函式。使?胓lib 只需要包含 gcc。資料夾操作函式。struct dirent,struct dir,opend...

Linux C語言標頭檔案搜尋路徑

本文介紹在linux中標頭檔案的搜尋路徑,也就是說你通過include指定的標頭檔案,linux下的gcc編譯器它是怎麼找到它的呢。在此之前,先了解乙個基本概念。標頭檔案是一種文字檔案,使用文字編輯器將 編寫好之後,以副檔名.h儲存就行了。標頭檔案中一般放一些重複使用的 例如函式宣告 變數宣告 常數...