本文已收錄至《Linux知識(shí)與編程》專(zhuān)欄!
作者:ARMCSKGT
演示環(huán)境:CentOS 7![]()
前言
當(dāng)我們安裝一款軟件成功后,桌面會(huì)多一個(gè)圖標(biāo),如果我們點(diǎn)擊圖標(biāo)就能啟動(dòng)軟件,但那個(gè)圖標(biāo)就是軟件本身嗎?顯然不是!圖標(biāo)只是軟件啟動(dòng)程序的一個(gè)快捷方式,在Linux中可以通過(guò)軟硬鏈接來(lái)創(chuàng)建類(lèi)似于Windows下的軟件快捷方式,Windows下創(chuàng)建快捷方式一般相當(dāng)于Linux中的軟連接;當(dāng)Windows中的一個(gè)軟件啟動(dòng)之后會(huì)加載各種文件,一般我們看到的軟件啟動(dòng)程序都很小,但是軟件安裝包卻很大,例如游戲,其實(shí)軟件中大部分都是庫(kù)文件,關(guān)于Linux下的庫(kù),本節(jié)將會(huì)詳細(xì)為您介紹!
正文
軟硬鏈接
關(guān)于軟硬鏈接,其中涉及Linux文件系統(tǒng)的知識(shí),如果有疑問(wèn),請(qǐng)先移步:Linux文件系統(tǒng)概述
原理
軟鏈接
軟鏈接又稱(chēng)為符號(hào)鏈接,軟鏈接是一個(gè)單獨(dú)的文件,啟動(dòng)這個(gè)軟鏈接程序會(huì)跳轉(zhuǎn)啟動(dòng)這個(gè)軟鏈接指向的程序,既然是一個(gè)單獨(dú)的文件,那么軟鏈接文件就擁有獨(dú)立的inode和文件屬性,軟鏈接的主要存儲(chǔ)內(nèi)容是源文件的地址,所以軟連接一般很小且依賴(lài)源文件!
因?yàn)檐涍B接非常依賴(lài)源文件,所以源文件一旦不存在或被源文件路徑出錯(cuò),再次啟動(dòng)該軟鏈接(快捷方式)則會(huì)出現(xiàn) No such file or directory 的錯(cuò)誤提示,表示系統(tǒng)沒(méi)有找到對(duì)應(yīng)文件!
當(dāng)我們刪除軟鏈接文件時(shí),并不會(huì)對(duì)源文件產(chǎn)生任何影響,就像我們刪除Windows桌面上的快捷方式并不是清除了該軟件一樣,想刪除該軟件必須刪除該軟件所在的安裝目錄!
硬鏈接
硬鏈接與軟鏈接不同,硬鏈接沒(méi)有獨(dú)立的inode和文件屬性,其只是在目錄中創(chuàng)建了與源文件inode和硬鏈接名的映射關(guān)系,并在源文件的文件屬性中引用計(jì)數(shù)進(jìn)行+1,表示增加了一個(gè)硬鏈接!
當(dāng)我們刪除一個(gè)硬鏈接時(shí),文件系統(tǒng)會(huì)判斷該鏈接的inode源文件ret_count計(jì)數(shù)是否為0,如果減去1后引用為0則刪除該文件,否則只是刪除該目錄下的一個(gè)硬鏈接映射關(guān)系且源文件引用計(jì)數(shù)-1,所以刪除硬鏈接文件,只有刪除最后一個(gè)硬鏈接才是真正刪除文件,否則也不會(huì)對(duì)源文件產(chǎn)生影響!
所以,硬鏈接并不在意源文件,因?yàn)橹灰叉溄哟嬖冢募痛嬖?,而軟鏈接的源文件被刪除則軟鏈接失效!
普通文件可以建立硬鏈接和軟鏈接,但是目錄只能建立軟鏈接!
當(dāng)我們新建一個(gè)文件時(shí),其默認(rèn)硬鏈接數(shù)為1,而目錄的默認(rèn)硬鏈接數(shù)為2
為什么新目錄的硬鏈接數(shù)為2? 因?yàn)樾履夸浥c父級(jí)目錄建立了硬鏈接
在Linux系統(tǒng)中, . 表示本目錄,**. .**表示上級(jí)目錄!
所以在父級(jí)目錄下,每創(chuàng)建一個(gè)新目錄,其硬鏈接數(shù)就會(huì)+1,因?yàn)樾履夸浥c父級(jí)目錄構(gòu)建的新的硬鏈接關(guān)系,但是Linux系統(tǒng)不允許用戶(hù)手動(dòng)為目錄創(chuàng)建硬鏈接,因?yàn)檫@樣會(huì)破壞文件系統(tǒng)的樹(shù)結(jié)構(gòu),嚴(yán)重時(shí)可能會(huì)變成圖,使得文件系統(tǒng)崩潰!
硬鏈接就像是淺拷貝,只拷貝了inode。
使用
生成軟鏈接文件:
$ ln -s 源文件路徑 軟鏈接文件名
注意:可以對(duì)目錄進(jìn)行軟鏈接,其方式與普通文件進(jìn)行軟鏈接方式相同!
生成硬鏈接文件:
$ ln 源文件路徑 軟鏈接文件名
雖然軟硬鏈接在使用上沒(méi)有差別,但是底層差別還是非常大的!
取消鏈接:
- 刪除鏈接文件
$ rm 鏈接文件
- unlink取消鏈接
$ unlink 鏈接文件
注意:普通文件的首個(gè)標(biāo)識(shí)符為 -,軟鏈接文件標(biāo)識(shí)符為 l,而硬鏈接本質(zhì)上是源文件的別名,所以也是普通文件 -!
文件時(shí)間
每一個(gè)文件從創(chuàng)建之日起就有三個(gè)時(shí)間(簡(jiǎn)稱(chēng)為 ACM 時(shí)間):
- 訪問(wèn)時(shí)間 Access :最后一次查看內(nèi)容的時(shí)間,如何判定取決于系統(tǒng)
- 修改屬性時(shí)間 Change:最后一次修改文件屬性的時(shí)間
- 修改內(nèi)容時(shí)間 Modify:最后一次修改文件內(nèi)容的時(shí)間
注意: 因?yàn)閙odify是文件屬性,modify修改了change也會(huì)修改;更改文件內(nèi)容與查看文件內(nèi)容不一樣,區(qū)別于access和modify,查看文件改變access,修改文件改變modify,Linux系統(tǒng)并非每次查看都會(huì)改變文件的access時(shí)間(因?yàn)樾薷腶ccess涉及文件屬性的修改需要讀取硬盤(pán)),有一定的策略,這樣可以減少與硬盤(pán)的交涉提高效率。
我們可以通過(guò) stat 命令查看文件屬性和ACM時(shí)間:
$ stat 文件名
動(dòng)靜態(tài)庫(kù)
庫(kù)介紹
原來(lái)在學(xué)習(xí)C語(yǔ)言時(shí),寫(xiě)一下學(xué)校課程設(shè)計(jì)可能會(huì)需要函數(shù)的聲明和定義進(jìn)行分離,這樣可以讓代碼顯得不凌亂!
其實(shí)圖中的test.cpp就可以充當(dāng)一個(gè)C/C++的函數(shù)庫(kù),但是我們?cè)谑褂脮r(shí)需要結(jié)合頭文件test.h一起使用!但是在實(shí)際的項(xiàng)目開(kāi)發(fā)過(guò)程中,一個(gè)保密的項(xiàng)目是不能透露庫(kù)中的源代碼的,我們只想留下 頭文件 聲明函數(shù)接口,而具體實(shí)現(xiàn)放在一個(gè)保密的庫(kù)中(別人可以使用,但是無(wú)法獲取函數(shù)實(shí)現(xiàn)),此時(shí)我們就需要引入動(dòng)靜態(tài)庫(kù)了!
說(shuō)明: 一般系統(tǒng)已經(jīng)預(yù)裝了C/C++頭文件和動(dòng)態(tài)庫(kù)文件,頭文件提供方法說(shuō)明,庫(kù)提供方法實(shí)現(xiàn),頭和庫(kù)是有對(duì)應(yīng)關(guān)系的,要組合在一起使用;頭文件是在預(yù)處理階段就引入的,鏈接的本質(zhì)其實(shí)就是鏈接庫(kù);引入庫(kù)文件一方面是為了提高開(kāi)發(fā)效率(代碼復(fù)用性等),另一方面可以保密!無(wú)論是在Linux系統(tǒng)中還是Windows系統(tǒng)中,都存在庫(kù),分為動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù),雖然不同環(huán)境下的后綴有所不同,但其工作原理是一致的!
- Linux 系統(tǒng)中:.a 后綴為靜態(tài)庫(kù),.so 后綴為動(dòng)態(tài)庫(kù)
- Windows 系統(tǒng)中:.lib 后綴為靜態(tài)庫(kù),.dll 后綴為動(dòng)態(tài)庫(kù)
在Linux系統(tǒng)中,庫(kù)命名一般為:libstdc++.so.6,去掉前綴 lib 和后綴 .so.6 ,剩下的就是庫(kù)名 stdc++ 。
我們可以使用命令查看Linux環(huán)境中的庫(kù)文件:# 查看C庫(kù) $ find /usr/lib64/libc* # 查看C++庫(kù) $ find /usr/lib64/libstdc* # 查看所有庫(kù) $ find /usr/lib64/lib
該圖只截取了一部分,實(shí)際上有很多庫(kù)!
在我們寫(xiě)C/C++程序時(shí),離不開(kāi)庫(kù)函數(shù),比如我們使用的各種STL容器,庫(kù)中只會(huì)提供給我們頭文件開(kāi)放接口進(jìn)行使用,并不會(huì)讓我們看到具體實(shí)現(xiàn),其具體實(shí)現(xiàn)已經(jīng)打包成庫(kù)(二進(jìn)制文件),在平時(shí)使用時(shí),編譯器默認(rèn)使用動(dòng)態(tài)庫(kù)而非靜態(tài)庫(kù),動(dòng)態(tài)庫(kù)在日常使用具有較大優(yōu)勢(shì)!
如果我們想指定使用靜態(tài)庫(kù)編譯,在gcc/g++下,只需要加上 -static 選項(xiàng)即可,但是前提是Linux環(huán)境中已經(jīng)安裝C/C++靜態(tài)庫(kù),一般服務(wù)器和虛擬機(jī)是沒(méi)有安裝的!
C/C++靜態(tài)庫(kù)的安裝(非root用戶(hù)需要sudo提權(quán)):# 安裝C靜態(tài)庫(kù) yum install -y glibc-static # 安裝C++靜態(tài)庫(kù) yum install -y libstdc++-static
動(dòng)靜態(tài)庫(kù)比較:
區(qū)別 靜態(tài)庫(kù) 動(dòng)態(tài)庫(kù) 空間大小 占用空間較大 占用空間小 調(diào)用方式 函數(shù)實(shí)現(xiàn)在程序中,直接在程序中執(zhí)行 通過(guò)地址轉(zhuǎn)到動(dòng)態(tài)庫(kù)中執(zhí)行動(dòng)代碼 加載速度 庫(kù)函數(shù)加載到程序中,空間占用大 多個(gè)程序共享一個(gè)已加載的動(dòng)態(tài)庫(kù),空間占用小 依賴(lài)性 直接在程序中運(yùn)行 依賴(lài)于動(dòng)態(tài)庫(kù) 補(bǔ)充: 動(dòng)態(tài)庫(kù)是在函數(shù)調(diào)用出留下地址鏈接,在調(diào)用該函數(shù)時(shí)轉(zhuǎn)到內(nèi)存中的動(dòng)態(tài)庫(kù)在指定的函數(shù)位置執(zhí)行代碼;而靜態(tài)庫(kù)是將函數(shù)實(shí)現(xiàn)直接拷貝到調(diào)用出,運(yùn)行時(shí)直接執(zhí)行!
簡(jiǎn)言之,如果沒(méi)有庫(kù)文件,那么你在開(kāi)發(fā)時(shí),需要自己手動(dòng)將 printf/cout 等高頻函數(shù)編寫(xiě)出來(lái),因此庫(kù)文件可以提高我們的開(kāi)發(fā)效率,比如 Python 中就有很多現(xiàn)成的庫(kù)函數(shù)可以使用,效率很高!
一般庫(kù)分為三種:
- 第一方庫(kù):語(yǔ)言自帶的庫(kù)
- 第二方庫(kù):操作系統(tǒng)提供的庫(kù)
- 第三方庫(kù):我們自己制作的庫(kù)或網(wǎng)上下載的庫(kù)
靜態(tài)庫(kù)
靜態(tài)庫(kù)制作
準(zhǔn)備庫(kù)文件和頭文件
add.hpp#pragma once int add(int a,int b);
add.cpp
#include "add.hpp" int add(int a,int b) { return a+b; }
sub.hpp
#pragma once int sub(int a,int b);
add.cpp
#include "sub.hpp" int sub(int a,int b) { return a-b; }
main.cpp
#include <iostream> #include "add.hpp" #include "sub.hpp" using namespace std; int main() { cout<<add(1,2)<<endl; cout<<sub(1,2)<<endl; return 0; }
編譯鏈接形成二進(jìn)制程序:
$ g++ main.cpp add.cpp sub.cpp -o exe -std=c++11
注意:聲明與定義分離的情況下,需要指明鏈接的函數(shù)實(shí)現(xiàn)文件
接下來(lái)開(kāi)始打包成靜態(tài)庫(kù),主要分為兩步:
- 1.將源文件進(jìn)行 預(yù)處理->編譯->匯編,生成可鏈接的二進(jìn)制 .o 文件
$ g++ -c add.cpp sub.cpp
執(zhí)行完畢后生成與文件名相同的 .o 二進(jìn)制鏈接文件
- 2.通過(guò) ar指令 將 .o 文件打包為靜態(tài)庫(kù)
#格式:ar -rc { lib靜態(tài)庫(kù)名.a } {鏈接文件1.o 鏈接文件2.o ...} $ ar -rc libmymath.a add.o sub.o # 也可以簡(jiǎn)寫(xiě)為:ar -rc libmymath.a *.o
注意:實(shí)際的靜態(tài)庫(kù)名為 mymath 但是gcc/g++編譯器會(huì)識(shí)別靜態(tài)庫(kù)自動(dòng)去掉頭(lib)尾(.a),按照規(guī)范我們必須這樣寫(xiě)!
此時(shí)就成功生成了靜態(tài)庫(kù)文件!
ar指令除了可以打包鏈接文件成為庫(kù)文件,還可以查看庫(kù)文件中的打包內(nèi)容:$ ar -tv {靜態(tài)庫(kù)文件.o}
靜態(tài)庫(kù)的使用
我們自己指針的庫(kù)是第三方庫(kù),在使用上區(qū)別與第一方和第二方庫(kù)區(qū)別很大!
此時(shí)如果我們直接編譯程序,是無(wú)法編譯的!
我們將上面使用和生成的文件進(jìn)行規(guī)整:
將頭文件放在_hpp目錄,庫(kù)文件放在lib,鏈接文件放在_o,實(shí)現(xiàn)文件放在_cpp,留下main.cpp在本目錄下,這樣在本目錄下就既沒(méi)有頭文件也沒(méi)有實(shí)現(xiàn)文件了,此時(shí)我們進(jìn)行靜態(tài)編譯!
1.直接使用靜態(tài)庫(kù)# 格式:g++ 代碼文件.cpp -I 頭文件夾路徑 -L 庫(kù)文件夾路徑 -l 靜態(tài)庫(kù)名(去掉頭尾) $ g++ main.cpp -o static_exe -I ./_hpp -L ./lib -l mymath -static #靜態(tài)鏈接 $ g++ main.cpp -o exe -I ./_hpp -L ./lib -l mymath #動(dòng)靜混合 # gcc使用方法與此相同
使用第三方庫(kù)與使用標(biāo)準(zhǔn)庫(kù)和系統(tǒng)庫(kù)不同,使用標(biāo)準(zhǔn)庫(kù)和系統(tǒng)庫(kù)都是系統(tǒng)級(jí)的,gcc/g++ 默認(rèn)找的就是 stdc/stdc++ 庫(kù),而第三方庫(kù)則需要我們自己指定!2.將頭文件和靜態(tài)庫(kù)文件安裝至系統(tǒng)庫(kù)下
Linux系統(tǒng)C/C++頭文件路徑:/usr/include/
Linux系統(tǒng)庫(kù)路徑:/lib64/# 注意:非root用戶(hù)需要sudo提權(quán) $ cp ./_hpp/*.hpp /usr/include/ $ cp ./lib/*.a /lib64/
將庫(kù)和頭文件安裝到系統(tǒng)目錄下后,只需要指定庫(kù)名即可完成編譯鏈接!
$ g++ main.cpp -o exe -l mymath #動(dòng)靜混合 $ g++ main.cpp -o static_exe -l mymath -static #靜態(tài)鏈接
注意:這里極其不提倡這種私自安裝外部庫(kù)的方式,將自己寫(xiě)的文件安裝到系統(tǒng)目錄下是一件危險(xiǎn)的事(導(dǎo)致系統(tǒng)環(huán)境被污染),如果不得已,用完后記得手動(dòng)刪除!關(guān)于靜態(tài)鏈接
靜態(tài)鏈接,是在鏈接時(shí)將調(diào)用函數(shù)處的函數(shù)調(diào)用替換為函數(shù)執(zhí)行代碼(二進(jìn)制代碼),可執(zhí)行程序從根本上脫離了庫(kù)的限制,在同系統(tǒng)的機(jī)器上無(wú)論是否有靜態(tài)庫(kù)都可以運(yùn)行,不依賴(lài)任何靜態(tài)庫(kù)!
靜態(tài)庫(kù)所體現(xiàn)的優(yōu)點(diǎn)是運(yùn)行比較快,但靜態(tài)鏈接形成的可執(zhí)行程序本身就有靜態(tài)庫(kù)中對(duì)應(yīng)方法的實(shí)現(xiàn)(將代碼拷貝到可執(zhí)行程序中),靜態(tài)鏈接的程序,非常占用資源,內(nèi)存中會(huì)程序多個(gè)重復(fù)的代碼(可執(zhí)行程序體積變大加載占用內(nèi)存),也占用磁盤(pán)資源,如果是給用戶(hù)用的軟件那么下載周期就會(huì)變長(zhǎng),占用網(wǎng)絡(luò)資源!
注意:如果要使用靜態(tài)鏈接需要加上 -static 否則編譯器將使用靜態(tài)庫(kù)進(jìn)行動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)的混合鏈接!
動(dòng)態(tài)庫(kù)
動(dòng)態(tài)庫(kù)制作
我們準(zhǔn)備與靜態(tài)庫(kù)制作相同的五個(gè)文件
打包為動(dòng)態(tài)庫(kù)分為兩步:
- 1.編譯源文件,生成二進(jìn)制可鏈接文件.o同時(shí)形成與位置無(wú)關(guān)碼
# 格式:gcc -c -fPIC {實(shí)現(xiàn)文件.cpp} $ g++ -c -fPIC add.cpp sub.cpp # gcc 使用方式與g++相同
同樣的,會(huì)形成 .o 鏈接文件!
說(shuō)明:fPIC這個(gè)選項(xiàng)是形成.o文件同時(shí)形成與位置無(wú)關(guān)碼,動(dòng)態(tài)庫(kù)中里面的代碼地址排布與靜態(tài)庫(kù)是有區(qū)別的,動(dòng)態(tài)庫(kù)經(jīng)常使用,所以gcc/g++自帶打包動(dòng)態(tài)庫(kù)功能。
- 2.打包鏈接文件形成動(dòng)態(tài)庫(kù)
# 格式:g++ -shared { 鏈接文件.o } -o { libmymath.so } g++ -o libmymath.so *.o -shared # gcc 使用方式與此相同
說(shuō)明:shared表示形成(打包成)動(dòng)態(tài)庫(kù)或共享文件動(dòng)態(tài)庫(kù)的使用
同樣的,我們先規(guī)整文件到不同的文件夾
我們使用靜態(tài)庫(kù)的方法去編譯可執(zhí)行程序:
$ g++ main.cpp -o exe -I ./_hpp -L ./lib -l mymath
之所以會(huì)運(yùn)行失敗,是因?yàn)楫?dāng)前只告訴了編譯器動(dòng)態(tài)庫(kù)的位置,沒(méi)有告訴 OS!
出現(xiàn)這種情況,可以使用 ldd 指令查看程序的鏈接情況:$ ldd 可執(zhí)行程序
動(dòng)態(tài)庫(kù)處,顯示狀態(tài)為沒(méi)有鏈接,未發(fā)現(xiàn)動(dòng)態(tài)庫(kù)!
這也說(shuō)明,我們不能盲目進(jìn)行鏈接,在此之前我們需要讓操作系統(tǒng)知道庫(kù)的位置,有三種方法:
- 1.修改臨時(shí)環(huán)境變量: 添加動(dòng)態(tài)庫(kù)路徑至 LD_LIBRARY_PATH 環(huán)境變量中;因?yàn)榄h(huán)境變量 LD_LIBRARY_PATH 是程序在進(jìn)行動(dòng)態(tài)庫(kù)查找時(shí)的默認(rèn)搜索路徑。
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/動(dòng)態(tài)庫(kù)目錄詳細(xì)(絕對(duì))路徑/
注意: 更改環(huán)境變量只是臨時(shí)方案,重新登錄bash后就失效了,需要重新配置
- 2.將動(dòng)態(tài)庫(kù)的軟鏈接文件存入系統(tǒng)目錄中
我們將動(dòng)態(tài)庫(kù)建立軟鏈接放入系統(tǒng)庫(kù)目錄中(普通用戶(hù)需要sudo提權(quán))# ln -s /動(dòng)態(tài)庫(kù)絕對(duì)路徑/ /lib64/動(dòng)態(tài)庫(kù)名稱(chēng)(與軟鏈接的動(dòng)態(tài)庫(kù)名稱(chēng)相同) $ ln -s /home/ARMCSKGT/演示文件夾/lib/libmymath.so /lib64/libmymath.so
注意: 創(chuàng)建軟連接文件時(shí),需要使用絕對(duì)路徑;這種方式的修改是永久有效的,但是我們不建議使用,如果非必要建議用后刪除,避免沖突和污染系統(tǒng)環(huán)境。
- 3.更改配置文件中的信息
系統(tǒng)的第三個(gè)動(dòng)態(tài)庫(kù)查找路徑就是前往動(dòng)態(tài)庫(kù)配置目錄的各配置文件提供的路徑中查找,我們可以寫(xiě)一個(gè)自己配置文件,里面寫(xiě)入動(dòng)態(tài)庫(kù)的路徑,放入該目錄中!$ touch mylib.conf #創(chuàng)建一個(gè)配置文件 $ echo /home/ARMCSKGT/演示文件夾/lib/ > mylib.conf #將動(dòng)態(tài)庫(kù)絕對(duì)路徑寫(xiě)入配置文件 $ mv mylib.conf /etc/ld.so.conf.d/ #將配置文件放入系統(tǒng)目錄/etc/ld.so.conf.d/中 $ ldconfig #重新加載系統(tǒng)配置文件
說(shuō)明: mv和ldconfig操作在普通用戶(hù)操作下需要sudo提權(quán)
注意: 這種方式的修改也是永久有效的,如果非必要建議用后刪除,避免沖突和污染系統(tǒng)環(huán)境。關(guān)于動(dòng)態(tài)鏈接
動(dòng)態(tài)庫(kù)的鏈接:將可執(zhí)行程序中的外部符號(hào)替換為庫(kù)中的具體地址,在程序執(zhí)行時(shí)直接將庫(kù)地址加載到內(nèi)存中,只要我們把庫(kù)加載到內(nèi)存,映射到進(jìn)程的地址空間中后,我們的代碼執(zhí)行庫(kù)中的方法,就依舊還是在自己的地址空間內(nèi)進(jìn)行函數(shù)跳轉(zhuǎn),當(dāng)庫(kù)因?yàn)槌绦蛘{(diào)用已經(jīng)在內(nèi)存中,另一個(gè)程序使用時(shí)就直接在頁(yè)表中映射然后在共享空間中調(diào)用即可!
動(dòng)態(tài)庫(kù)的方法只需要在內(nèi)存中存在一份就可以被所有進(jìn)程使用了,庫(kù)的加載也不一定是全部加載到內(nèi)存,使用什么加載什么就行,具體根據(jù)操作系統(tǒng)的策略就行操作。
程序在鏈接動(dòng)態(tài)庫(kù)函數(shù)時(shí),是通過(guò) 動(dòng)態(tài)庫(kù)起始地址 + 所鏈接函數(shù)偏移量 的方式進(jìn)行鏈接訪問(wèn)的,而這個(gè)偏移量就是 fPIC 與位置無(wú)關(guān)碼!
地址就兩類(lèi):絕對(duì)編址 and 相對(duì)編制
靜態(tài)鏈接時(shí),將可鏈接的二進(jìn)制文件加載至程序中,直接通過(guò) 絕對(duì)地址 進(jìn)行鏈接,如果函數(shù)被調(diào)用了多次,就會(huì)導(dǎo)致代碼冗余等問(wèn)題。
動(dòng)態(tài)鏈接采用 相對(duì)地址 的方式進(jìn)行鏈接,同一個(gè)函數(shù)的 動(dòng)態(tài)庫(kù)起始地址 + 所鏈接函數(shù)偏移量 值相同,代碼只需要加載一份,并且可以任意位置進(jìn)行函數(shù)調(diào)用(與位置無(wú)關(guān))。
動(dòng)態(tài)庫(kù)必定面臨一個(gè)問(wèn)題:不同的進(jìn)程,運(yùn)行程度不同,需要使用的第三方庫(kù)不同,注定了每一個(gè)進(jìn)程的共享空間中的空閑位置是不確定的
動(dòng)態(tài)庫(kù)中的地址,絕對(duì)不能確定,去使用絕對(duì)編址,動(dòng)態(tài)庫(kù)中的所有地址都是偏移量,默認(rèn)從0地址開(kāi)始,當(dāng)一個(gè)庫(kù)真正被映射到地址空間時(shí),他的起始地址才能真正確定,動(dòng)態(tài)庫(kù)在進(jìn)程的地址空間中隨便加載,與我們加載到地址空間的什么位置毫無(wú)關(guān)系!
補(bǔ)充
當(dāng)同時(shí)存在動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)時(shí),編譯器默認(rèn)采用動(dòng)態(tài)庫(kù)!
如果我們想指定生成靜態(tài)庫(kù)程序,只需要加上 -static 選項(xiàng)即可:$ g++ [代碼文件.cpp] -static #如果是第三方庫(kù)需要指定頭文件,庫(kù)路徑和庫(kù)名稱(chēng)
如果只提供靜態(tài)庫(kù),但編譯時(shí)不加-static,編譯時(shí)會(huì)將靜態(tài)庫(kù)進(jìn)行靜態(tài)鏈接(結(jié)合具體的情況)(將可以動(dòng)態(tài)鏈接的庫(kù)動(dòng)態(tài)鏈接,然后將不能動(dòng)態(tài)鏈接的靜態(tài)庫(kù)中代碼拷貝到文件中),可以動(dòng)態(tài)鏈接的庫(kù)進(jìn)行動(dòng)態(tài)鏈接!
靜態(tài)鏈接生成的程序比動(dòng)態(tài)鏈接大得多,并且內(nèi)含靜態(tài)庫(kù)的動(dòng)態(tài)鏈接程序,也比純粹的動(dòng)態(tài)鏈接程序大,說(shuō)明程序不是 非靜即動(dòng),可以同時(shí)使用動(dòng)態(tài)庫(kù)與靜態(tài)庫(kù)!
最后
以上就是 【Linux軟硬鏈接和動(dòng)靜態(tài)庫(kù)】 的全部?jī)?nèi)容了,本節(jié)我們結(jié)束了如同快捷方式一樣的軟硬鏈接,讓我們可以對(duì)目標(biāo)建立鏈接快速訪問(wèn),同時(shí)學(xué)習(xí)了程序的運(yùn)行需要庫(kù)的加持,動(dòng)靜態(tài)庫(kù)的區(qū)別,學(xué)習(xí)了制作庫(kù),最后介紹了庫(kù)的鏈接原理,相信本次的介紹可以幫助各位開(kāi)發(fā)者!
本次 <Linux軟硬鏈接和動(dòng)靜態(tài)庫(kù)> 就先介紹到這里啦,希望能夠盡可能幫助到大家。
如果文章中有瑕疵,還請(qǐng)各位大佬細(xì)心點(diǎn)評(píng)和留言,我將立即修補(bǔ)錯(cuò)誤,謝謝!文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-713192.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-713192.html
??其他文章閱讀推薦??
Linux<文件系統(tǒng)概述> -CSDN博客
Linux<重定向和緩沖區(qū)理解> -CSDN博客
Linux<文件理解和系統(tǒng)調(diào)用> -CSDN博客
Linux<進(jìn)程控制> -CSDN博客
Linux<進(jìn)程地址空間> -CSDN博客
??歡迎讀者多多瀏覽多多支持!??
到了這里,關(guān)于Linux軟硬鏈接和動(dòng)靜態(tài)庫(kù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!