目錄
一、認識一下常用指令
1、建立一個軟鏈接
2、建立一個硬鏈接
3、刪除文件的第二種方式:刪除鏈接unlink指令
二、什么是硬鏈接?
三、軟硬鏈接的原理:
四、應用場景
1、建立一個軟鏈接可以快速在一個比較深的路徑中找到目標文件進行執行:
2、觀察現象:
3、硬鏈接使用場景之一:
五、動態庫和靜態庫
1、ldd:查看動態庫鏈接
2、動靜態庫使用過程
靜態庫(.a文件)
動態庫(.so文件)
3、動靜態庫注意事項
4、動靜態庫的制作和使用
(1)?$^:所有依賴項列表
(2)$<:第一個依賴項
5、將.c文件鏈接上動靜態庫
I(大寫i)選項
查看頭文件所在路徑:ls /usr/inlcude/
6、打包/安裝注意事項
7、修改make文件,使動靜態庫都能形成
8、幾個結論
六、理解動態加載
七、簡單談談編址和可執行程序
前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家
點擊跳轉到網站
一、認識一下常用指令
1、建立一個軟鏈接
指令:ln -s [源文件或目錄] [目標軟鏈接]
軟鏈接即上述的link.soft本質上也是個文件,有獨立的inode。
2、建立一個硬鏈接
指令:
ln [源文件] [目標硬鏈接]
我們可以觀察到兩個現象:
(1)硬鏈接的inode和源文件相同:
所以可以知道硬鏈接本質不是一個獨立文件,因為inode和源文件一樣。
(2)我們看一個屬性由數字1變成了數字2。
當我們刪除硬鏈接或者源文件,這個數字又會由2變1:
這個屬性類似于引用計數,我們稱這個屬性叫硬鏈接數
3、刪除文件的第二種方式:刪除鏈接unlink指令
該指令和rm類似:
二、什么是硬鏈接?
由上我們可以知道,硬鏈接不是一個獨立文件,所以創建硬鏈接的過程并沒有創建新文件,硬鏈接類似于引用計數,只是新的文件名,和源文件的inode號有映射關系。
每增加一組映射,inode結構體中存在一個引用計數就會++,也是就是硬鏈接數會++。
注意:
三、軟硬鏈接的原理:
四、應用場景
1、建立一個軟鏈接可以快速在一個比較深的路徑中找到目標文件進行執行:
因為軟鏈接保存的就是目標文件路徑。
2、觀察現象:
當我們創建一個文件夾時,硬鏈接數剛開始默認就是2,為什么吶?
因為創建一個目錄的同時會默認創建兩個文件
.而當前目錄(.)就代表當前目錄test1,所以存在兩個文件名映射同一個inode,所以test1文件的硬鏈接數是2。
3、硬鏈接使用場景之一:
首先認識一個結論:計算一個目錄下有多少個子目錄:目錄硬鏈接數-2
因為每個子目錄都存在一個默認文件(..)代表上級目錄,子目錄的上級目錄就是當前目錄。
因為會造成環路問題,所以系統不允許我們為目錄創建硬鏈接:
但系統可以為目錄創建硬鏈接,比如(.)和(..);
五、動態庫和靜態庫
1、ldd:查看動態庫鏈接
- 左邊?
libc.so.6
?是程序編譯、運行時期望找到的動態庫 “邏輯名稱”(可理解為別名 )。- 右邊是系統中實際存在的動態庫文件路徑(物理位置),系統會根據這個映射,在程序加載時找到真實的?
libc.so.6
?去提供功能支持。- 并且編譯程序時,默認是進行動態鏈接,如果想要進行靜態鏈接,需要使用選項“-static"
?
- 動態庫后綴:.so
- 靜態庫后綴:.a
- 庫的真實名字是去掉前面的lib,去掉后面的后綴(.so/.a)剩下的就是庫真實名字,比如上述的libc.so.6真實名字就是c(c標準庫)。
2、動靜態庫使用過程
靜態庫(
.a
文件)
- 編譯時 “拷貝整合”:編譯鏈接階段,鏈接器會把靜態庫中被程序調用的代碼完整復制到可執行文件里。程序運行時,無需再去外部找庫,直接執行內部代碼,省去了 “運行時加載庫” 的開銷,啟動速度更快?。
- 避免運行時動態開銷:沒有動態加載、符號解析等運行時流程,代碼執行流程更直接,對追求極致啟動速度和獨立運行環境(不依賴外部庫)的場景友好,比如嵌入式設備里,程序可脫離外部依賴快速啟動執行。
動態庫(
.so
文件)
- “共享復用” 省資源:多個程序可共享同一份動態庫。系統加載動態庫到內存后,不同程序調用時,復用已加載的庫代碼,減少內存、磁盤重復存儲(一個庫文件給多個程序用,不用每個程序都存一份庫代碼),提升系統整體資源效率。
- “延遲綁定” 減啟動耗時:借助 PLT(過程鏈接表)和 GOT(全局偏移表)實現延遲綁定?。程序啟動時,不著急解析、綁定所有外部符號(函數 / 變量),第一次調用外部符號時,才去查找地址并記錄到 GOT 。后續調用直接用記錄的地址,避免啟動時 “一次性解析所有符號” 的性能浪費,讓程序啟動更快,尤其適合依賴多、但實際運行不會用到全部符號的復雜程序。
3、動靜態庫注意事項
首先為什么要有庫?
(1)為了提高效率
(2)可以隱藏源代碼
庫的本質就是將所有的.o文件用特定的方式進行打包整合,形成一個大文件,最后得到一堆頭文件和一個庫文件,但這只是簡化后的概念,具體還很復雜。
注意:庫里面不能含有main函數,因為main只能有一個。
4、動靜態庫的制作和使用
(1)gcc的-shared選項:用來打包動態庫:
(2)gcc的-FPIC選項:
讓動態庫能被加載到任意內存地址,多個程序可共享同一份庫代碼(節省內存);避免因庫加載地址沖突導致的鏈接 / 運行錯誤。
(3)make文件常用符號解析:
(1)?
$^
:所有依賴項列表
- 含義:表示規則中所有的依賴文件,按書寫順序排列,重復的依賴項會被保留。
- 示例:若規則為
target: file1 file2 file3
,則$^
等價于file1 file2 file3
。(2)
$<
:第一個依賴項
- 含義:僅表示依賴項列表中的第一個文件。
- 示例:上述規則中,
$<
等價于file1
。
5、將.c文件鏈接上動靜態庫
# 鏈接動態庫 gcc main.o -L./libs -lmylib -o main # 生成可執行程序 main# 若鏈接靜態庫(需確保 libs/ 目錄有 libmylib.a) gcc main.o -L./libs -static -lmylib -o main # -static 強制靜態鏈接
(1)-L后面接的是庫路徑,-l后面接的是指定庫名
(2)gcc可以默認識別c/c++的庫和系統中的路徑,所以除了-L指定的路徑,gcc還會去系統默認的路徑中查找c/c++庫。
6、發布庫的過程:
I(大寫i)選項
查看頭文件所在路徑:ls /usr/inlcude/
6、打包/安裝注意事項
若直接將動態庫打包過來安裝后用指令編譯,雖然編譯可以通過,但運行時會報錯:(靜態庫是可以的)
原因如下:
四種解決方法:
(1)
(2)認識一個環境變量:$LD_LIBRARY_PATH:
?Linux里的環境變量,專門用于指定動態鏈接庫(
.so
?文件,類似 Windows 下的?.dll
?)的搜索路徑。我們將不在系統默認搜索路徑下的庫路徑添加到該環境變量中即可。
跟PATH一致,當重新登錄時,會恢復到默認路徑。
(3)建立一個軟鏈接
(4)將庫路徑保存到一個配置文件中
注意事項:
7、修改make文件,使動靜態庫都能形成
8、幾個結論
(1)如果我們同時提供動態庫和靜態庫,gcc默認使用的是動態庫;
(2)如果我們非要使用靜態庫,需要使用static選項
(3)
(4)
六、理解動態加載
1、庫默認就是一個磁盤級別的文件,當動態庫加載之后,會被映射到進程地址空間的共享區中。
2、
3、