九色91_成人精品一区二区三区中文字幕_国产精品久久久久一区二区三区_欧美精品久久_国产精品99久久久久久久vr_www.国产视频

Hello! 歡迎來到小浪云!


【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫


avatar
小浪云 2025-04-17 38

Ⅰ. 前言

? 我們之前學(xué) gcc 的時(shí)候也有接觸過一點(diǎn)動(dòng)靜態(tài)庫的知識,現(xiàn)在要把它單獨(dú)拿出來講,主要是因?yàn)槲覀兒竺婵隙ㄔ谧约洪_發(fā)的時(shí)候需要包裝自己的庫,此時(shí)就需要有動(dòng)靜態(tài)庫的原理知識和使用知識!

? 一般庫名稱都是中間部分,也就是去掉前綴和后綴的部分剩下的內(nèi)容,如:libc.so,去掉前綴 lib,去掉后綴 .so -> c 動(dòng)態(tài)庫。

? 靜態(tài)庫和動(dòng)態(tài)庫最本質(zhì)的區(qū)別就是:該庫是否被編譯進(jìn)目標(biāo)(程序)內(nèi)部。

? 下面我們一一介紹它們!

? 在介紹之前我們先來介紹兩個(gè)我們也曾經(jīng)講過的指令:

? 第一個(gè)就是 ldd 指令,它的功能是 顯示可執(zhí)行文件依賴的庫 。

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

? 第二個(gè)指令就是 file 可執(zhí)行文件 指令,用于 查看程序是動(dòng)態(tài)還是靜態(tài)鏈接。

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

Ⅱ. 靜態(tài)庫一、靜態(tài)庫的概念

? 靜態(tài)庫:這類的函數(shù)庫通常擴(kuò)展名為 libxxx.a 或 xxx.lib 。工作原理是程序在編譯鏈接的時(shí)候把庫的代碼鏈接 (拷貝) 到可執(zhí)行文件中,變成可執(zhí)行文件中的一部分,所以 程序運(yùn)行的時(shí)候?qū)⒉辉傩枰o態(tài)庫。

? 這類庫在編譯的時(shí)候會(huì)直接整合到目標(biāo)程序中,所以利用 靜態(tài)函數(shù)庫編譯成的文件會(huì)比較大,這類函數(shù)庫最大的優(yōu)點(diǎn)就是編譯成功的可執(zhí)行文件 可以獨(dú)立運(yùn)行,而不再需要向外部要求讀取函數(shù)庫的內(nèi)容;但是從升級難易度來看明顯沒有優(yōu)勢,如果函數(shù)庫更新,需要重新編譯。

? 靜態(tài)鏈接:鏈接靜態(tài)庫,每個(gè)程序?qū)⒆约涸趲熘杏玫降闹噶畲a單獨(dú)寫入自己可執(zhí)行程序中,程序 運(yùn)行時(shí)無依賴,加載運(yùn)行速度快,但是程序運(yùn)行后有可能會(huì)有 冗余代碼 在內(nèi)存中。

二、ar指令

? ararchiver)命令可以用來 創(chuàng)建、查詢、修改庫。庫是一組單獨(dú)的文件,里面包含了按照特定的結(jié)構(gòu)組織起來的源文件,原始文件的內(nèi)容、模式、時(shí)間戳、屬性、組等屬性都保留在庫文件中。

? 下面是命令選項(xiàng):

代碼語言:JavaScript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

复制代码
  1. -d:刪除庫文件中的成員文件-m:變更成員文件在庫文件中的次序-p:顯示庫文件中的成員文件內(nèi)容-q:將文件附加在庫文件末端-r:將文件插入庫文件中-t:顯示庫文件中所包含的文件-x:從庫文件中取出成員文件-a:將文件插入庫文件中指定的成員文件之后-b:將文件插入庫文件中指定的成員文件之前-c:建立庫文件-f:截掉要放入庫文件中過長的成員文件名稱-i:將文件插入庫文件中指定的成員文件之前-o:保留庫文件中文件的日期-s:若庫文件中包含了對象模式,可利用此參數(shù)建立備存文件的符號表-S:不產(chǎn)生符號表-u:只將日期較新文件插入庫文件中-v:程序執(zhí)行時(shí)顯示詳細(xì)的信息-V:顯示版本信息

下面介紹幾個(gè)常用的:

參數(shù) r :在庫中插入或替換模塊。當(dāng)插入的模塊名已經(jīng)在庫中存在,則替換同名的模塊。如果若干模塊中有一個(gè)模塊在庫中不存在,ar 顯示一個(gè)錯(cuò)誤消息,并不替換其他同名模塊。默認(rèn)的情況下,新的成員增加在庫的結(jié)尾處,不過也可以使用其他任選項(xiàng)來改變增加的位置。參數(shù) c :創(chuàng)建一個(gè)庫。不管庫是否存在,都將創(chuàng)建。參數(shù) s :創(chuàng)建目標(biāo)文件索引,這在創(chuàng)建較大的庫時(shí)能加快時(shí)間。(補(bǔ)充:如果不需要?jiǎng)?chuàng)建索引,可改成大寫 S 參數(shù);如果 .a 文件缺少索引,可以使用 ranlib 命令添加)參數(shù) t :比如 ar t libxxx.a,表示顯示庫文件中有哪些目標(biāo)文件,只顯示名稱。參數(shù) v :比如 ar tv libxxx.a,表示顯示庫文件中有哪些目標(biāo)文件,顯示文件名、時(shí)間、大小等詳細(xì)信息。nm -s libxxx.a :顯示庫文件中的索引表。ranlib libxxx.a :為靜態(tài)庫文件創(chuàng)建索引表。三、靜態(tài)庫的封裝

? 封裝庫就是將多個(gè) .o 文件打包到一個(gè)文件中,所以我們可以使用 gnu 中的歸檔指令 ar -rc (其中 ar 代表 archiver,rc 選項(xiàng)表示 replace and create)封裝一個(gè)靜態(tài)庫。

? 所以下面我們用 makefile 將封裝指令使用起來,形成我們的靜態(tài)庫 libmymath.a :

代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

复制代码
  1. libmymath.a : add.o sub.o # 使用ar指令封裝靜態(tài)庫ar -rc $@ $^ %.o : %.c # %的作用是匹配目錄下的.c文件集合生成.o文件集合,與*號類似,但是%多用于makefile,且使用范圍不太一樣gcc -c $<cleanclean:rm libmymath.a mylib><figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174488066080163.jpg" alt="【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫"></figure><p>? 這樣子還不夠,因?yàn)槲覀儾粌H僅需要將庫發(fā)給對方,我們還需要將頭文件也打包起來發(fā)給對方,考慮到如果頭文件太多也不好管理的情況,我們最好自己將頭文件和庫放在一個(gè)目錄下打包起來,所以我們可以在 makefile 中添加一個(gè)偽目標(biāo) output,其中我們調(diào)用 make output 的時(shí)候希望其能創(chuàng)建一個(gè)目錄將我們需要打包的頭文件和庫打包到一個(gè)目錄下:</p>代碼語言:javascript<i class="icon-code"></i>代碼運(yùn)行次數(shù):<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" style="max-width:90%" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>運(yùn)行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>復(fù)制<pre class="prism-token token line-numbers javascript">.PHONY : output # output作為偽目標(biāo)進(jìn)行打包頭文件和靜態(tài)庫output:mkdir -p mylib/includemkdir -p mylib/libcp -f *.a mylib/libcp -f *.h mylib/include
【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

? 除此之外,如果我們想安裝,也就是說這個(gè)庫和頭文件我希望不只是被對方使用,還能在我這個(gè)系統(tǒng)上面使用,所以可以安裝這些庫和頭文件,其實(shí)本質(zhì)就是將頭文件放到 /usr/include 中,庫放到對應(yīng)的庫目錄中比如 /lib64 中,所以我們現(xiàn)在也能清楚,安裝的本質(zhì)就是將頭文件拷貝到系統(tǒng)的頭文件目錄下,庫拷貝到系統(tǒng)的庫目錄下!

? 參考下面代碼,這里就不貼調(diào)用效果了:

代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

复制代码
  1. .PHONY:installinstall:sudo cp *.h /usr/include # 注意一般拷貝到系統(tǒng)目錄的時(shí)候要sudo一下sudo cp *.a /lib64

?

? 最后我們將這個(gè) mylib 目錄壓縮變成一個(gè)包,一般采用 tar 指令進(jìn)行壓縮,現(xiàn)在,我們的軟件就已經(jīng)發(fā)布出來了,我們就可以將其打包然后放在網(wǎng)站或者 yum 的資源中供別人進(jìn)行下載使用了:

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

四、靜態(tài)庫的使用

? 為什么要把靜態(tài)庫的使用單獨(dú)拎出來說呢,因?yàn)槠渲杏泻芏嗫樱S多人打包完卻因?yàn)楹芏噙@些坑導(dǎo)致這些庫都調(diào)不起來,所以我們要好好來講一下!

? 下面假設(shè)我們在別的目錄下的 main.c 中調(diào)用該庫,在這之前先將這個(gè)包解壓到 main.c 目錄下:

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

? 接下來有了這個(gè) mylib ,我們不就可以直接編譯鏈接 main.c 為可執(zhí)行文件了嗎,下面我們來試試看:

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

? 奇怪,明明我們的庫和頭文件都有啊,為什么還報(bào)錯(cuò)說找不到頭文件呢 ? ? ?

? 仔細(xì)一想,我們之前在學(xué)c語言的時(shí)候講過,如果頭文件使用雙引號括起來的,那么它首先會(huì)到源文件的當(dāng)前目錄下查找,但是我們好像把庫和頭文件都放在了 mylib 中,深度相對于源文件更深了一點(diǎn),所以 main.o 在鏈接的時(shí)候就找不到了!

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

? 不僅如此,就算我們等會(huì)解決了這個(gè)問題還會(huì)遇到其它問題,這里就不賣關(guān)子了,直接將幾個(gè)問題的解決方法一次性給出:

? 當(dāng)我們鏈接庫時(shí),必須指定庫的名稱,這是因?yàn)橥宦窂较驴赡芡瑫r(shí)存在許多庫(頭文件不需要指定名稱,只需指定路徑,因?yàn)?main 中指明了我們需要的頭文件名稱),同時(shí),庫需要去掉前綴 lib 和 后綴 .a 或者 .so 才是庫真正的名稱,也就是在我們編譯鏈接可執(zhí)行文件的時(shí)候需要在 gcc 或者其它指令后面 指定頭文件路徑、庫文件路徑、庫文件名稱(注意要去掉前綴和后綴):

代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

复制代码
  1. gcc -o main main.c -I./mylib/include -L./mylib/lib -lmymath-I 指定頭文件路徑:告訴編譯器在./xxx路徑中找頭文件-L 指定庫文件路徑:告訴編譯器在./xxx路徑找?guī)?l 指定庫文件名:庫名稱(去掉前綴lib,去掉后綴.so或.a

? 其中不管 -I 還是 -L ,其實(shí)它們和路徑之間是可以不留空格的,一般我們的書寫習(xí)慣也是不留空格!

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

? 為了方便,我們可以在 makefile 中將這些選項(xiàng)加入:

代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

复制代码
  1. libmymath.a : add.o sub.o # 使用ar指令封裝靜態(tài)庫ar -rc $@ $^ -I./mylib/include -L./mylib/lib -lmymath%.o : %.cgcc -c $<outputoutput:mkdir mylib libmymath.a><p>? 平時(shí)我們使用編譯器提供的庫并不需要帶這些選項(xiàng),是因?yàn)榫幾g器有自己的環(huán)境變量(LIBRARY_PATH),能夠找到位于 /lib64 庫文件的存放目錄和 /usr/include 頭文件的存放目錄。</p> <p>? 所以我們可以將我們寫的靜態(tài)庫和頭文件放入這些目錄或其他相關(guān)目錄下,這就是一般軟件的安裝過程。但是不推薦,因?yàn)榉胚M(jìn)去會(huì)污染標(biāo)準(zhǔn)庫(可能不安全)。</p>五、靜態(tài)鏈接的一個(gè)小問題<p>? 接下來還有一個(gè)問題,我們查看一下我們生成的可執(zhí)行文件的屬性看看:</p> <figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174488066173494.jpg" alt="【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫"></figure><p>? 這里還存在一個(gè)奇怪的地方:main 的依賴庫中并看不到 libmymath.a,并且 main 是動(dòng)態(tài)鏈接的;這是由如下原因造成的:</p> <p>? 1、gcc 默認(rèn)使用動(dòng)態(tài)鏈接(只是建議行為),這是針對動(dòng)靜態(tài)庫都存在的情況說的,如果只存在靜態(tài)庫,那么 Linux 也只能使用靜態(tài)鏈,但是如果存在動(dòng)態(tài)庫,即使指明 Static 選項(xiàng)也只會(huì)使用動(dòng)態(tài)鏈接;</p> <p>? 2、一個(gè)可執(zhí)行程序的形成可能不僅僅只依賴一個(gè)庫,如果依賴的庫中有一部分不只有靜態(tài)庫,有一部分庫有動(dòng)態(tài)庫,那么形成的可執(zhí)行程序整體是動(dòng)態(tài)鏈接的,但其中只有靜態(tài)庫的地方才會(huì)進(jìn)行靜態(tài)鏈接;</p> <p>? 3、這里的現(xiàn)象和第二點(diǎn)一樣,main 的形成不僅僅依賴一個(gè)庫 (使用了 C 語言庫函數(shù)),且 Linux 中存在 C 語言動(dòng)態(tài)庫,所以這里是使用動(dòng)態(tài)鏈接的,而我們自己的庫 libmymath.a 以靜態(tài)的方式進(jìn)行鏈接。</p>Ⅲ. 動(dòng)態(tài)庫1、動(dòng)態(tài)庫的概念<p>? 動(dòng)態(tài)庫:這類函數(shù)庫通常名為 libxxx.so 或 xxx.dll 。</p> <p>? 與靜態(tài)函數(shù)庫被整個(gè)捕捉到程序中不同,動(dòng)態(tài)函數(shù)庫在編譯的時(shí)候,在程序里只有一個(gè) “指向庫” 的位置而已,也就是說當(dāng) 可執(zhí)行文件需要使用到函數(shù)庫的機(jī)制時(shí),程序才會(huì)去讀取函數(shù)庫來使用;也就是說 可執(zhí)行文件無法單獨(dú)運(yùn)行。這樣從產(chǎn)品功能升級角度方便升級,只要替換對應(yīng)動(dòng)態(tài)庫即可,不必重新編譯整個(gè)可執(zhí)行文件。</p> <p>? 動(dòng)態(tài)庫可以在多個(gè)程序間共享,所以動(dòng)態(tài)鏈接使得 可執(zhí)行文件更小,節(jié)省了磁盤空間。<a style="color:#f60; text-decoration:underline;" title="操作系統(tǒng)" href="https://www.php.cn/zt/16016.html" target="_blank">操作系統(tǒng)</a>采用 虛擬內(nèi)存機(jī)制允許物理內(nèi)存中的一份動(dòng)態(tài)庫被要用到該庫的所有進(jìn)程共用,節(jié)省了內(nèi)存和磁盤空間。</p> <p>? 一個(gè)與動(dòng)態(tài)庫鏈接的可執(zhí)行文件僅僅包含它用到的函數(shù)入口地址的一個(gè)表,而不是外部函數(shù)所在目標(biāo)文件的整個(gè)機(jī)器碼。這種鏈接方式,是用于解決靜態(tài)庫存在的浪費(fèi)內(nèi)存和磁盤空間,以及解決模塊更新困難等問題。</p> <p>? 動(dòng)態(tài)鏈接生成可執(zhí)行程序,可執(zhí)行程序中會(huì)記錄自己依賴的庫列表以及庫中的函數(shù)地址信息,等到運(yùn)行程序的時(shí)候,由操作系統(tǒng)將庫加載到內(nèi)存中(多個(gè)程序可以共享,不需要加載多份相同實(shí)例),然后根據(jù)庫加載后的地址在對每個(gè)程序內(nèi)部用到的庫函數(shù)的地址進(jìn)行偏移計(jì)算。</p> <p>? 動(dòng)態(tài)庫也叫運(yùn)行時(shí)庫,是運(yùn)行時(shí)加載的庫,將庫中數(shù)據(jù)加載到內(nèi)存中后,每個(gè)使用了動(dòng)態(tài)庫的程序都要根據(jù)加載的起始位置計(jì)算內(nèi)部函數(shù)以及變量地址,因此動(dòng)態(tài)鏈接動(dòng)態(tài)庫加載及運(yùn)行速度是不如靜態(tài)鏈接的,但是它也有好處,就是多個(gè)程序在內(nèi)存中只需要加載一份動(dòng)態(tài)庫就可以共享使用。</p> <figure class=""><hr></figure><p>基于這么一種思想,動(dòng)態(tài)鏈接具有以下優(yōu)缺點(diǎn):</p> <p>優(yōu)點(diǎn):</p>節(jié)省內(nèi)存并減少頁面交換;庫文件與程序文件獨(dú)立,只要輸出接口不變,更換庫文件不會(huì)對程序文件造成任何影響,因而極大地提高了可維護(hù)性和可擴(kuò)展性;不同編程語言編寫的程序只要按照函數(shù)調(diào)用約定就可以調(diào)用同一個(gè)庫函數(shù);適用于大規(guī)模的軟件開發(fā),使開發(fā)過程獨(dú)立、耦合度小,便于不同開發(fā)者和開發(fā)組織之間進(jìn)行開發(fā)和測試。<p>缺點(diǎn):</p>運(yùn)行時(shí)依賴,所以找不到庫文件就會(huì)運(yùn)行失敗加載動(dòng)態(tài)庫的程序運(yùn)行速度相對較慢,因?yàn)閯?dòng)態(tài)庫運(yùn)行時(shí)加載,映射到虛擬地址空間后需要重新根據(jù)映射起始地址計(jì)算函數(shù)/變量地址需要對庫版本之間的兼容性做出更多處理二、動(dòng)態(tài)庫的封裝<p>動(dòng)態(tài)庫的制作和靜態(tài)庫存在很多相似的地方,但也有不同:</p>動(dòng)態(tài)庫匯編 形成 .o 文件需要指定 fPIC 選項(xiàng),用于 形成位置無關(guān)碼(與位置無關(guān),庫文件可以在內(nèi)存的任意位置加載,不影響其他程序的關(guān)聯(lián)性)動(dòng)態(tài)庫歸檔不使用 ar 指令,而是 在 gcc 中指定 shard 選項(xiàng)就可以完成歸檔工作,表示生成共享庫形式。<p>? 同樣的,知道封裝動(dòng)態(tài)庫的知識后,我們將所有 .o 文件進(jìn)行打包并與頭文件合并成目錄:</p>代碼語言:javascript<i class="icon-code"></i>代碼運(yùn)行次數(shù):<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>運(yùn)行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>復(fù)制<pre class="prism-token token line-numbers javascript">libmymath.so : add.o sub.o # 加上-shared封裝靜態(tài)庫gcc -shared -o $@ $^ %.o : %.c # %的作用是匹配目錄下的.c文件集合生成.o文件集合,與*號類似,但是%多用于makefile,且使用范圍不太一樣gcc -fPIC -c $<figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174488066285836.jpg" alt="【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫"></figure>三、動(dòng)態(tài)庫的使用<p>? 和靜態(tài)庫一樣,我們先將 mylib 目錄文件壓縮,然后發(fā)到使用方那邊再解壓。接著還是一樣,我們在編譯鏈接成可執(zhí)行文件的時(shí)候必須加上三個(gè)選項(xiàng):頭文件路徑、庫文件路徑、庫文件名! </p><figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174488066289355.jpg" alt="【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫"></figure><p>? 很奇怪啊,為什么找不到我們寫的動(dòng)態(tài)庫呢,我們明明已經(jīng)把頭文件路徑、庫文件路徑和庫文件名都加上去了啊,為什么還是找不到啊 ? ? ?</p><p>? 其實(shí)是因?yàn)殡m然說我們是告訴了 gcc 我們的頭文件路徑等,但是當(dāng)我們編譯鏈接生成可執(zhí)行文件之后,gcc 可就不管我們了啊,我們執(zhí)行一個(gè)可執(zhí)行文件,這是和操作系統(tǒng)有關(guān)系的,通過加載到內(nèi)存變成進(jìn)程從而管理,但是操作系統(tǒng)哪里知道我們告訴了它這些頭文件路徑等等呢,并且我們的庫也不在系統(tǒng)中,所以 操作系統(tǒng) 和 shell 才會(huì)找不到!</p><p>? 所以要執(zhí)行可執(zhí)行文件的話我們必須告訴 操作系統(tǒng) 和 shell 關(guān)于庫的路徑!下面介紹四種方法!</p>方案一:更改環(huán)境變量LD_LIBRARY_PATH – 短暫性<p>? 在系統(tǒng)中有個(gè)環(huán)境變量叫做 LD_LIBRARY_PATH,其中該環(huán)境變量中放的就是一些指定的動(dòng)態(tài)鏈接庫的路徑,我們可以利用 export 指令將我們要存放的動(dòng)態(tài)鏈接庫的路徑添加進(jìn)去,注意要添加絕對路徑! </p><figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174488066236729.jpg" alt="【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫"></figure><p>? 這里需要注意的是:添加環(huán)境變量后,默認(rèn)只在本次登錄有效,下次登錄時(shí)無效(默認(rèn)清理登錄前一次添加環(huán)境變量)。如果想讓這個(gè)環(huán)境變量永久生效,可以把這個(gè)環(huán)境變量添加到登錄相關(guān)的啟動(dòng)腳本里,下面兩個(gè)都行,但是不建議,如果真要改,多開幾個(gè)終端,防止改了之后登不上 Linux:</p>代碼語言:javascript<i class="icon-code"></i>代碼運(yùn)行次數(shù):<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" style="max-width:90%" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>運(yùn)行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>復(fù)制<pre class="prism-token token line-numbers javascript">vim ~/.bash_profilevim ~/.bashrc

方案二:將動(dòng)態(tài)庫和頭文件拷貝至對應(yīng)的系統(tǒng)庫路徑(/lib64)和頭文件路徑(/usr/include)下(不推薦)

? 這個(gè)我們上面講過,這里就不講了,并且不推薦,因?yàn)闀?huì)污染系統(tǒng)文件池!

方案三:配置文件 –永久性代碼語言:javascript代碼運(yùn)行次數(shù):0運(yùn)行復(fù)制

复制代码
  1. [liren@VM-8-2-centos use_library]$ ll -d /etc/ld.so.conf.d/drwxr-xr-x. 2 root root 4096 Jul 25 2022 /etc/ld.so.conf.d/

? 在我們系統(tǒng)中存在一個(gè)系統(tǒng)搜索動(dòng)態(tài)庫的路徑配置文件目錄 /etc/ld.so.conf.d/ ,我們可以在這個(gè)目錄創(chuàng)建 .conf 配置文件,向配置文件中添加我們的動(dòng)態(tài)庫的 絕對路徑 即可?。ㄟ@個(gè)配置文件的名稱是可以隨便取的)

? 添加絕對路徑后,我們還要使用 ldconfig 指令來更新一下這些配置文件,才能生效!

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

方案四:創(chuàng)建軟鏈接

? 在當(dāng)前文件路徑下建立軟鏈接,注意這個(gè)軟鏈接的名稱要和動(dòng)態(tài)庫的名稱一樣,因?yàn)樵趯ふ規(guī)斓臅r(shí)候我們指定了用庫文件名!

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

Ⅳ. 動(dòng)靜態(tài)庫的加載一、靜態(tài)庫的加載

? 首先,我們要知道,靜態(tài)庫不需要加載!

? 這個(gè)過程,在磁盤中 main.c 和 lib.c 庫,會(huì)先在磁盤中形成一段代碼,然后對這段代碼進(jìn)行編譯,編譯的本質(zhì)就是預(yù)處理,編譯-查找錯(cuò)誤,形成二進(jìn)制代碼,然后進(jìn)行匯編形成二級制指令。在編譯階段的時(shí)候就已經(jīng)形成了虛擬地址空間。

? 在虛擬地址空間中,這段代碼也就被存入代碼區(qū),這個(gè)是根據(jù)不同區(qū)的特性所決定的。當(dāng)執(zhí)行這段代碼的時(shí)候,操作系統(tǒng)就會(huì)直接在代碼區(qū)進(jìn)行訪問。

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

二、動(dòng)態(tài)庫的加載

? 動(dòng)態(tài)庫加載的過程,在磁盤中有一個(gè) my.exe(可執(zhí)行)和 lib.so(動(dòng)態(tài)庫),在形成可執(zhí)行之前,編譯階段時(shí),我們用到了 fPIC(產(chǎn)生位置無關(guān)碼)。

? 在這個(gè)階段,動(dòng)態(tài)庫會(huì)將指定的函數(shù)地址,寫入到可執(zhí)行文件中。這個(gè)地址可以理解成 my_add.c(地址) + 偏移地址。

? 形成可執(zhí)行文件之后,磁盤將可執(zhí)行文件拷貝到內(nèi)存中,內(nèi)存通過頁表映射到虛擬地址空間的代碼區(qū)中,當(dāng) OS 執(zhí)行程序時(shí),掃描到 my_add.c 是需要調(diào)用動(dòng)態(tài)庫的時(shí)候,程序會(huì)停下來,OS 會(huì)再通過函數(shù)的地址,然后頁表映射去內(nèi)存到磁盤中找動(dòng)態(tài)庫中,找到后拷貝到內(nèi)存,又通過頁表映射到共享區(qū)中。OS 再去 共享區(qū) 調(diào)用該方法,然后向下執(zhí)行程序。

? 注意:動(dòng)態(tài)庫可以避免靜態(tài)庫內(nèi)存空間浪費(fèi)的問題,這是由于如果多個(gè)進(jìn)程鏈接了同一個(gè)動(dòng)態(tài)庫,動(dòng)態(tài)庫也只需要加載一次。動(dòng)態(tài)庫被加載到物理內(nèi)存中并通過頁表映射到某一個(gè)進(jìn)程(假設(shè)A進(jìn)程)的共享區(qū)之后,操作系統(tǒng)會(huì)記錄該動(dòng)態(tài)庫在A進(jìn)程共享區(qū)中的地址,當(dāng)其他進(jìn)程也需要執(zhí)行動(dòng)態(tài)庫代碼時(shí),操作系統(tǒng)會(huì)根據(jù)記錄的地址加上偏移量通過頁表跳轉(zhuǎn)到A進(jìn)程的共享區(qū)中執(zhí)行函數(shù),執(zhí)行完畢后再跳回到當(dāng)前進(jìn)程地址空間的代碼段處。

? 所以 從始至終物理內(nèi)存中都只有一份動(dòng)態(tài)庫代碼。

【Linux系統(tǒng)IO】六、動(dòng)靜態(tài)庫

相關(guān)閱讀

主站蜘蛛池模板: 亚洲精品久久久久久一区二区 | 亚洲h色| 免费观看色 | 在线观看免费av网站 | 欧美综合视频 | jizz视频| 国产一二三区免费视频 | 日韩中文字幕一区 | 国产精品久久久久久久久久三级 | 国产精品一区在线观看你懂的 | 日本精品一区二区三区在线观看视频 | 美日韩精品 | 成人av免费网站 | 国产亚洲成av人片在线观看桃 | 日韩精品久久一区二区三区 | 激情欧美日韩一区二区 | 日韩精品一区二区三区中文在线 | 精品日韩 | 国产在线不卡视频 | 国产欧美一区二区三区久久手机版 | 国产乱码精品1区2区3区 | 成人在线视频网 | 福利色导航 | 亚洲淫视频| 日韩精品久久一区二区三区 | 欧美日韩一区二区在线播放 | 91久久久久久 | 亚洲国产精品久久久久婷婷老年 | 中文字幕在线看第二 | 久久久久国产一区二区三区 | 国产综合久久久久久鬼色 | 美女艹b | 亚洲成人a v | 91中文视频 | 国产成人免费视频网站高清观看视频 | 日韩在线一区二区三区 | 国产视频2021 | av大片在线 | 91影院| 99婷婷| 奇米四色在线观看 |