亚洲国产第一_开心网五月色综合亚洲_日本一级特黄特色大片免费观看_久久久久久久久久免观看

Hello! 歡迎來到小浪云!


Linux軟硬鏈接與動靜態(tài)庫


avatar
小浪云 2025-04-17 25

linux系統(tǒng)中,文件名并不直接指向磁盤上的文件,而是通過inode進行關聯(lián)。多個文件名可以指向同一個inode,這在linux中被稱為硬鏈接。

Linux軟硬鏈接與動靜態(tài)庫

例如,文件abc和def具有相同的鏈接狀態(tài),它們都是指向inode 789665的硬鏈接。這個inode的硬鏈接數(shù)為2。當刪除文件時,系統(tǒng)會執(zhí)行兩個操作:1. 從目錄中刪除相應的記錄;2. 將硬鏈接數(shù)減1,如果硬鏈接數(shù)變?yōu)?,則釋放對應的磁盤空間。

1.2 軟鏈接

硬鏈接通過inode引用另一個文件,而軟鏈接則是通過文件名來引用另一個文件。軟鏈接和被引用的文件擁有不同的inode,可以看作是文件系統(tǒng)中的快捷方式。在Shell中,創(chuàng)建軟鏈接的方式如下:

Linux軟硬鏈接與動靜態(tài)庫Linux軟硬鏈接與動靜態(tài)庫

1.3 軟硬鏈接的對比

軟鏈接是一個獨立的文件,而硬鏈接只是文件名與目標文件inode之間的映射關系。

1.4 軟硬鏈接的用途

硬鏈接:

  • 常用于備份文件。
  • 例如.和..就是硬鏈接。

軟鏈接:

  • 類似于快捷方式,常用于創(chuàng)建指向其他文件的引用。

2. 什么是庫

庫是已經(jīng)編寫好的、成熟的、可復用的代碼。在實際應用中,每個程序都依賴于許多基礎的底層庫,不可能從零開始編寫所有代碼,因此庫的存在非常重要。

庫本質(zhì)上是可執(zhí)行代碼的二進制形式,可以被操作系統(tǒng)加載到內(nèi)存中執(zhí)行。庫分為兩種類型:

  • 靜態(tài)庫:在Linux中為.a文件,在Windows中為.lib文件。
  • 動態(tài)庫:在Linux中為.so文件,在Windows中為.dll文件。

centos系統(tǒng)中,c語言c++語言的動靜態(tài)庫如下:

C語言:

Linux軟硬鏈接與動靜態(tài)庫Linux軟硬鏈接與動靜態(tài)庫

C++語言:

Linux軟硬鏈接與動靜態(tài)庫

3. 制作動靜態(tài)庫

預備工作:

Linux軟硬鏈接與動靜態(tài)庫

3.1 靜態(tài)庫

靜態(tài)庫(.a文件)在程序編譯鏈接時將其代碼鏈接到可執(zhí)行文件中,程序運行時不再需要靜態(tài)庫。一個可執(zhí)行程序可能使用多個庫,這些庫可以是靜態(tài)庫或動態(tài)庫。默認情況下,編譯器會使用動態(tài)鏈接庫,只有在找不到相應的.so文件時,才會使用同名的靜態(tài)庫。可以使用gcc的-Static選項強制使用靜態(tài)庫。

3.1.1 靜態(tài)庫的生成

Linux軟硬鏈接與動靜態(tài)庫Linux軟硬鏈接與動靜態(tài)庫

注釋:argnu歸檔工具,rc表示替換和創(chuàng)建。

Linux軟硬鏈接與動靜態(tài)庫

t選項列出靜態(tài)庫中的文件,v選項提供詳細信息。

3.1.2 靜態(tài)庫的使用

在任意目錄下,新建main.c文件并引入庫頭文件:

#include "my_stdio.h" #include "my_string.h" #include <stdio.h>  int main() {     const char *s = "abcdefg";     printf("%s: %dn", s, my_strlen(s));     mFILE *fp = mfopen("./log.txt", "a");     if(fp == NULL) return 1;     mfwrite(s, my_strlen(s), fp);     mfwrite(s, my_strlen(s), fp);     mfwrite(s, my_strlen(s), fp);     mfclose(fp);     return 0; }

場景一:頭文件和庫文件都已安裝到系統(tǒng)路徑下。

頭文件安裝到系統(tǒng)路徑:

Linux軟硬鏈接與動靜態(tài)庫

庫文件安裝到系統(tǒng)路徑:

Linux軟硬鏈接與動靜態(tài)庫

此時直接編譯gcc main.c會出現(xiàn)鏈接錯誤,因為系統(tǒng)路徑下gcc默認只會鏈接C的標準庫,第三方庫需要明確指定:

$ gcc main.c -lmystdio // -l 表示指定鏈接的庫,空格可帶可不帶

場景二:頭文件和庫文件與源文件在同一路徑下。

頭文件查找規(guī)則是先查找同級目錄,再查找系統(tǒng)目錄,因此頭文件不會報錯,但庫文件只會在系統(tǒng)路徑下查找,需要指定庫路徑:

$ gcc main.c -L. -lmymath // -L表示指明庫的路徑

場景三:頭文件和庫文件都有各自獨立的路徑。

Linux軟硬鏈接與動靜態(tài)庫

找不到頭文件,因為頭文件和main.c不在同一級目錄下,也不位于系統(tǒng)目錄:

Linux軟硬鏈接與動靜態(tài)庫

此時找到頭文件,但庫文件找不到:

Linux軟硬鏈接與動靜態(tài)庫

有庫的路徑但不知道鏈接哪個庫:

Linux軟硬鏈接與動靜態(tài)庫

此時編譯成功:

$ gcc main.c -I頭文件路徑 -L庫文件路徑 -lmymath // -I指明頭文件路徑

總結:

測試目標文件生成后,刪除靜態(tài)庫,程序仍然可以運行。庫文件名稱和引入庫文件名稱:去掉前綴lib,去掉后綴.so或.a,例如libc.so -> c。

3.2 動態(tài)庫

動態(tài)庫(.so文件)在程序運行時才進行鏈接,多個程序可以共享使用庫的代碼。一個與動態(tài)庫鏈接的可執(zhí)行文件僅包含它所用到的函數(shù)入口地址表,而非外部函數(shù)所在目標文件的整個機器碼。在可執(zhí)行文件開始運行前,外部函數(shù)的機器碼由操作系統(tǒng)從磁盤上的動態(tài)庫中復制到內(nèi)存中,這個過程稱為動態(tài)鏈接(dynamic linking)。動態(tài)庫可以在多個程序間共享,因此動態(tài)鏈接使得可執(zhí)行文件更小,節(jié)省了磁盤空間。操作系統(tǒng)通過虛擬內(nèi)存機制允許物理內(nèi)存中的一份動態(tài)庫被所有使用該庫的進程共享,節(jié)省了內(nèi)存和磁盤空間。

3.2.1 動態(tài)庫的生成

Linux軟硬鏈接與動靜態(tài)庫

shared選項表示生成共享庫格式,fPIC選項產(chǎn)生位置無關碼(position independent code)。庫名規(guī)則為libxxx.so:

Linux軟硬鏈接與動靜態(tài)庫

3.2.2 動態(tài)庫的使用

場景一:頭文件和庫文件安裝到系統(tǒng)路徑下。

Linux軟硬鏈接與動靜態(tài)庫Linux軟硬鏈接與動靜態(tài)庫

此時直接編譯會導致鏈接錯誤,與靜態(tài)庫類似:

Linux軟硬鏈接與動靜態(tài)庫

$ gcc main.c -lmystdio

Linux軟硬鏈接與動靜態(tài)庫

場景二:頭文件和庫文件與源文件在同一路徑下。

$ gcc main.c -L. -lmymath // 從左到右搜索-L指定的目錄

場景三:頭文件和庫文件都有各自獨立的路徑。

$ gcc main.c -I頭文件路徑 -L庫文件路徑 -lmymath

使用ldd查看可執(zhí)行文件依賴哪些庫:

Linux軟硬鏈接與動靜態(tài)庫

問題1

Linux軟硬鏈接與動靜態(tài)庫

如果刪除庫中的文件,會導致如下錯誤:

Linux軟硬鏈接與動靜態(tài)庫

這是因為動態(tài)鏈接的特性,刪除庫文件會導致鏈接錯誤,而靜態(tài)鏈接則不會。

解決方案

  • 拷貝.so文件到系統(tǒng)共享路徑下,通常是/usr/lib, /usr/local/lib, /lib64等。
  • 在系統(tǒng)共享路徑下建立同名的軟鏈接。

Linux軟硬鏈接與動靜態(tài)庫

Linux系統(tǒng)會查找動態(tài)庫和環(huán)境變量,可以通過更改環(huán)境變量LD_LIBRARY_PATH來指定動態(tài)庫路徑:

Linux軟硬鏈接與動靜態(tài)庫Linux軟硬鏈接與動靜態(tài)庫

但重啟Xshell后,導入的環(huán)境變量會丟失,可以將環(huán)境變量添加到.bashrc文件中:

Linux軟硬鏈接與動靜態(tài)庫

使用ldconfig方案:配置/etc/ld.so.conf.d/,然后使用ldconfig更新:

Linux軟硬鏈接與動靜態(tài)庫

將庫的路徑寫入配置文件,系統(tǒng)會在配置文件中的路徑查找?guī)欤孕袆?chuàng)建一個配置文件:

Linux軟硬鏈接與動靜態(tài)庫

然后在命令行輸入ldconfig,即可生效。

程序運行時與gcc無關,gcc是告訴編譯器接下來操作系統(tǒng)要加載你的程序。

如何讓系統(tǒng)指定路徑查找自己的動態(tài)庫,上述就是解決方案。

問題2:如果同時提供.so和.a,gcc/g++默認使用什么庫?

默認使用動態(tài)庫:

Linux軟硬鏈接與動靜態(tài)庫Linux軟硬鏈接與動靜態(tài)庫

如果想要靜態(tài)鏈接,需要添加-static選項:

Linux軟硬鏈接與動靜態(tài)庫

注意:

如果你要強制靜態(tài)鏈接,必須提供對應的靜態(tài)庫。如果只提供靜態(tài)庫但連接方式是動態(tài)鏈接,gcc/g++沒有選擇,只能針對你的.a文件局部采用靜態(tài)鏈接。因此,如果從系統(tǒng)路徑中刪除庫文件,程序仍然可以運行。


完,您的點贊和收藏是我更新的最大動力!!!

相關閱讀