1 環境變量的概念和使用
1.1 基本概念
環境變量一般是指在操作系統中用來指定操作系統運行環境./應用程序環境的一些變量
path 就是一個環境變量,一般來說應用程序的執行需要帶上路徑才可以運行,而定義在環境變量path 中的路徑,系統會自動識別,因此對應的應用程序只需要程序名稱即可運行。
1.2 基本配置
1 Windows 中的配置
我的電腦 -屬性- 高級-環境變量-系統變量-path -點編輯,在path 變量後面增加分號,用於分隔路徑,在追加新的路徑,設置確定,
注意不要刪除原來Path 變量原來的變量值,避免出現系統無法啟動或者正常運行的情況
2 UNIX/Linux系統中的配置
echo 字符串 表示字符串原樣輸出,回顯
echo $SHELL 表示獲取SHELL 的值,進行回顯
echo $PATH 獲取PATH 的值進行回顯打印
export PATH=$PATH:. 解釋 export 表示導入,PATH 表示環境變量
$PATH 表示把變量值的取出來。獲取環境變量中原來的數值。後面的就是自己加上的路徑,:代表分隔,.代表當前的路徑
所以這句話的意思就是把當前目錄的路徑追加到環境變量的值中。
echo $SHELL
但是這行指令只是針對當前終端有效,一次性的。
vi ~/.bashrc 打開文件,在文件最後增加代碼,~/代表主目錄下,.開頭代表隱藏文件,是bash 的配置文件。在這裡配置就是永久性的,
export PATH=$PATH:.
export PS1='\W$' 這裡 '\W$'表示只顯示一個單詞,$結尾。
表示終端的提示符只顯示一個單詞,使用$結尾
source ~/.bashrc
使得配置文件立即生效
1.3 編程相關的環境變量
C_INCLUDE_PATH/CPATH-C c頭文件的附加搜索路徑,這裡沒下劃線。
CPLUS_INCLUDE_PATH-C++ C++頭文件的附加搜索路徑
LIBRARY_PATH - 鏈接庫文件時候查找路徑
LD_LIBRARY_PATH - 運行時查找共享庫的路徑
1.4 頭文件的查找方式
1 #include
表示去系統默認的路徑中查找該頭文件
whereis +文件 查找文件位置。
2 #include“xxx”
表示優先在當前工作目錄下進行查找,這個雙引號之內可以加路徑,就是../這樣,我靠 這也可以,我以前都沒見過。
如果保證代碼不變進行對C文件的頭文件庫進行配置
export CPATH=$CPATH:..
這樣可以設置頭文件的包含路徑
3 配置環境變量
export CPATH =$CPATH:..
一次性的,永久的需要加入bash中。這種配置的缺陷是,當有多個工程的時候,環境變量的位置可能引發沖突。
4 使用編譯選項 -I
gcc/cc *.c -I 頭文件目錄
gcc/cc *.c -I ..
最好的方案了,建議使用這種方案,
注意
對於查找頭文件的方式12 來說,缺點是一旦頭文件的位置發生改變,需要修改源代碼,3 的缺陷是多個工程會相互影響,建議使用方案4;
練習
多文件編程結構,實現計算兩個int 類型參數的和,通過返回值返回的自定義函數。
2 庫文件的概念
1.1 概念
為了調用者使用方便,一般不會直接提供對應的.c或者.o文件,而是根據具體的功能模塊,將對應的多個.o 文件打包一個/多個庫文件,給調用者提供庫文件和頭文件即可。
庫文件主要分成兩種, 靜態庫和共享庫
1 靜態庫
1 靜態庫使用時候,直接把代碼復制到目標文件中,
優缺點
優點 就是 不需要跳轉,效率比較高,脫離靜態庫。
缺點 目標文件比較大,維護和修改都不方便
2 共享庫
共享庫使用時候,是把代碼的地址復制過來,
優點 目標文件比較小,維護和修改都比較方便
缺點 需要跳轉,效率低,不能脫離共享庫文件
基本命令
ldd +可執行文件 可以得到他所鏈接的文件
gcc/cc -static *.c -o b.out 強制要求使用靜態庫方式生成可執行文件
比較發現靜態庫方式生成的文件比較大
2.2靜態庫的生成和使用
1 靜態庫的生成
a 編寫源代碼 xxx.c
b 只編譯不鏈接生成目標文件 xxx.o文件
gcc/cc -c add.c
c 生成靜態庫文件
ar -r / 插入/ lib庫名.a 目標文件
ar -r libadd.a add.0
注意
靜態庫的文件名的命名規則, 以lib 開頭,以.a 結尾
靜態庫文件名和庫名是不同的概念,庫名沒前綴和後綴
2 靜態庫的使用步驟
a 編寫測試源代碼 xxx.c
b 只編譯不鏈接生成目標文件 xxx.o
gcc/cc -c main.c
c 鏈接測試文件和靜態庫文件,連接方式有三種
1 直接鏈接
cc main.o libadd.a
2 編譯選項進行編譯鏈接
gcc/cc main.o -l 庫名 -L 庫文件所咋的路徑
gcc/cc mian.o -l add -L .
3 掌握第二種就可以,第三種是第二種的變形,配置環境變量LIBRARY_PATH
export LIBRARY_PATH =$LIBRARY_PATH:.
gcc/cc main.o -l add 省略了第二種之中的路徑
使用是直接鏈接靜態庫文件就可以生成可執行文件,鏈接時候可以鏈接多個靜態庫文件。
cp -r 復制整個文件夾, cp 復制一個文件。
共享庫的生成和使用步驟
1 生成步驟
1 編寫源碼
2 只編譯不連接生成目標文件
gcc/cc -c -fpic //小模式代碼少) add.c
3 生成共享庫文件
gcc /cc -shared 目標文件 -o lib庫名.so
gcc/cc -shared /共享/ add.o -o libadd.so
2 共享庫的使用
a 編寫測試源代碼 xxx.c
b 只編譯不鏈接生成目標文件 xxx.o
gcc/cc -c main.c
c 鏈接測試文件和共享庫文件,連接方式有三種
1 直接鏈接
cc main.o libadd.so
2 編譯選項進行編譯鏈接
gcc/cc main.o -l 庫名 -L 庫文件所咋的路徑
gcc/cc mian.o -l add -L .
3 掌握第二種就可以,第三種是第二種的變形,配置環境變量LIBRARY_PATH
export LIBRARY_PATH =$LIBRARY_PATH:.
gcc/cc main.o -l add 省略了第二種之中的路徑
ldd 查看共享庫的信息
直接生成運行的時候會發生錯誤,找不到共享庫文件。需要配置運行時的共享庫環境變量配置。
export LD_LIBRARY_PATH =$LD_LABRARY_PATH:.
注意事項,共享庫的實現需要要求配置環境變量,LD_LIBRARY_PATH 的值,主要解決運行時找不到共享庫的問題。
記住步驟,先用別的文件生成庫文件,而後生成源碼的.o 文件,而後進行鏈接 鏈接主要是第二種方法,第一種是直接鏈接比較簡單,第三種是第二種的改編, gcc/cc main.o -l add -L .最後的是文件的路徑,我的虛擬機出了問題我不能自己直接鏈接了
共享庫的動態加載
1 dlopen 函數
動態加載共享庫功能函數的接口函數,
#include
void *dlopen (const char * filename,int flag);
dlopen 第一個參數是共享庫文件的函數名,第二個是int型標志位,返回值是void * 是viod 類型的函數指針。就是句柄,暫時理解為首地址。
函數功能是打開和加載庫文件。
如果調用失敗,返回一個空地址NULL;成功就返回句柄。
傳遞第二個實參,必須包括兩個參數 RTLD_LAZY和 RTLD_NOW。第一個表示延遲加載,第二個表示立即加載。
2 dlerror char *dlerror (void);
返回的就是dlopen dlclose dlsym 三個函數的最近發生的一個錯誤信息。返回NULL則表示沒有錯誤發生。
3 dlsym 函數
void *dlsym(void * handle,const char *symbol);
第一個參數要的是一個句柄信息,也就是dlopen 這個函數的返回值
第二個參數 字符串形式的符號,表示函數名
返回值:成功返回的是函數在內存中的地址,失敗返回NULL,
函數功能:主要用於根據句柄和函數名獲取在內存中的地址。
4 dlclose 函數,int dlclose (void *handle );
參數是dlopen 的返回值,用來關閉dlopen 的返回值所指定的共享庫,就是回收動態庫在加載中所占有的空間。
5
返回0 表示成功,返回非零表示失敗。當共享庫不在被函數使用的時候,不在被任何程序使用時候,則收回共享庫所占有的空間。
注意:編譯鏈接時候需要增加選項:-ldl
共享庫的動態加載。dynamic
編程實現打印空心的菱形和實心的菱形。對打印函數所在的文件分別打包成靜態庫文件和共享庫文件進行調用。