自我名言:只有努力,才能追逐夢想,只有努力,才不會欺騙自己。
喜歡的點贊,收藏,關注一下把!
文件分為:被打開的文件和沒被打開的文件,前面兩篇博文主要講解的是進程與被打開文件的關系。今天這篇博客講的是沒被打開的文件如何在磁盤上存放,文件系統(tǒng)如何管理文件,以及軟硬連接。
1.理解文件系統(tǒng)
問:沒有被打開的文件,該如何被操作系統(tǒng)管理呢?
沒有被打開的文件,只能在磁盤上靜靜的放著,磁盤上有大量的文件,也必須被管理(靜態(tài)管理)起來,方便我們隨時打開。這些工作是由文件系統(tǒng)做的。
在理解文件系統(tǒng)之前,我們必須搞懂磁盤上的文件是怎么存的。
我們似乎還沒有見過磁盤,這里先補充一些磁盤的有關知識。
1.1磁盤的物理結構
我們目前很少看見磁盤了,使用最多的就是SSD固定硬盤。
磁盤是我們計算機中唯一的一個機械結構!
磁盤是一個機械結構+外設,所有磁盤訪問速度很慢(相對于CPU和內(nèi)存來說)。
但是在企業(yè)端,磁盤依舊是存儲主流。磁盤具有造價低,存儲量大等特點。。。
注意:磁頭和盤面沒有接觸! 距離就像一架波音747在距離地面一米高速飛行。
為什么這樣說呢?因為盤片一秒可以上萬轉(zhuǎn)。
當盤面高速旋轉(zhuǎn)時,磁頭會漂浮起來。
磁盤還需要防止抖動。雖然盤面看起來光滑的,但是表明是存儲數(shù)據(jù)的地方,如果磁盤抖動導致磁頭把盤面刮花就會丟失數(shù)據(jù),就好像以往,看碟片出現(xiàn)花紋情況,就是出現(xiàn)了數(shù)據(jù)丟失。
1.2磁盤的存儲結構
磁盤的存儲是分為那個磁道,那個盤面,那個扇區(qū)的。
問:磁盤尋址的時候,基本單位是bit,還是byte?
注意,磁盤尋址的時候,基本單位既不是bit,更不是byte,而是一塊塊扇區(qū)。也就是說數(shù)據(jù)都在扇區(qū)放著。
每一塊扇區(qū)都是512byte。靠近圓心存儲密度急,遠離圓心密度疏。
如果在單面上,如何定位一個扇區(qū)呢?
首先要確定在那個磁道。
其次確定在對應磁盤的哪一個扇區(qū)。
那如何確定在那個磁道呢?
其實磁頭來回擺動的時候,就是在確定在哪一個磁道。
如何確定在哪一個扇區(qū)?
盤面在高速旋轉(zhuǎn)的時候,就是讓磁頭定位扇區(qū)。
一個盤片有兩個盤面,兩個盤面都可以存儲數(shù)據(jù),那另一面怎么存儲數(shù)據(jù)?
有多少盤面就有多少磁頭。并且這些磁頭是共進退的。
那如何在磁盤中,定位任何一個扇區(qū)呢?
1.先定位在哪一個磁道/柱面(因此磁頭是共進退的,磁道一旦確認,所以磁頭就不動了)。
2.在定位哪一個磁頭(也就是確認在哪一個盤面)。
3.最后定位在哪一個扇區(qū)。
磁道(track),柱面(cylinder),磁頭(head),扇區(qū)(sector)。
因此,磁盤中定位任何一個扇區(qū),采用的硬件級別定位方式:CHS定位法!
1.3磁盤的邏輯結構
還記得磁帶嗎?卷起來是圓的,扯出來是線性結構。
磁盤物理上也是圓形,在邏輯上想象成線性結構。
假設這個磁盤只有兩個盤片,四個盤面,三個柱面
我們把整個磁盤從邏輯上看做一個sector arr[n],把對磁盤的管理,變成對數(shù)組進行管理。
請問現(xiàn)在要找到一個扇區(qū),該如何找到呢?
這時,只需要直到這個扇區(qū)的"下標",就可以定位一個扇區(qū)!
而在操作系統(tǒng)內(nèi)部,稱這種地址為LBA地址(邏輯塊地址)。
假設盤面:4,磁道/柱面:10,扇區(qū):100,扇區(qū)大?。?12byte。
4 * 10 * 100 * 512=總容量(byte)
4 * 10 * 100=下標范圍
在物理層面上磁盤定位一個扇區(qū)采用的是CHS定位法,那么操作系統(tǒng)如何將邏輯上LBA地址(線性地址)轉(zhuǎn)化成CHS對應方案呢?
假設下標123
123/1000=0 —> 0號盤面 H
123/100=1 —> 1號磁道 C
123%100=1 —> 1號扇區(qū) S
操作系統(tǒng)以這樣的算法將LBA地址轉(zhuǎn)化成磁盤能認識的CHS地址,進而訪問磁盤的地址。
為什么OS要進行邏輯抽象呢?直接用CHS不行嗎?
1.便于管理(是管理一個數(shù)組號,還是三維立體結構好呢?)
2.不想讓操作系統(tǒng)代碼和硬件強耦合(如果底層用的是SSD,或者其他硬件存呢?OS只需把LBA轉(zhuǎn)化成其他的就行了)
雖然磁盤的訪問基本單位是512byte,但是依舊很小?。。ㄏ胱x取4KB內(nèi)容需要8次IO)。知道木桶原理就知道,訪問速度根據(jù)最低來進行的。因此OS內(nèi)的文件系統(tǒng)定制的進行多個扇區(qū)的讀取---->1KB,2KB,4KB為基本單位。所以哪怕只想讀取1bit,也必須要將4KB加載到內(nèi)存,進行讀取或者修改,如果有必要再寫回磁盤!
操作系統(tǒng)的文件系統(tǒng)一般默認以4KB大?。ㄒ簿褪?個扇區(qū))為基本單位來進行系統(tǒng)和磁盤IO的過程。
內(nèi)存也是被劃分成為4KB大小的空間被OS進行內(nèi)存管理------頁框
磁盤中的文件尤其是可執(zhí)行文件,按照4KB大小劃分好的塊-----頁幀
把文件加載到內(nèi)存就是把數(shù)據(jù)放到頁框里。
假設磁盤500G,我們看如何存儲文件的。
假設一個磁盤劃分4個盤,C/D/E/F盤,其實就是把整個磁盤劃區(qū)。
如果能把100G大小空間管理好,直接把辦法對其他區(qū)復制粘貼整個磁盤就可以管理好。
現(xiàn)在對每個區(qū)分組。
如果我把5G大小空間管理好,對其他分組進行復制粘貼,這100G也能管理好。
具體來看看文件系統(tǒng)是如何對空間進行管理的
1.4文件系統(tǒng)
Boot Block:分區(qū)的開頭,是分區(qū)表。存放各種分區(qū)的情況,如OS系統(tǒng)在那個分區(qū),圖形化界面在那個區(qū)等。
Super Block:保存的整個文件系統(tǒng)的信息,整個分區(qū)有多少分組,起始塊號,結束塊號是多少等等,而且并不是每個分組都有這個Super Block,只存在于一個或者多個分組。
那為什么Super Block不放在分區(qū)而放在分組呢?
這樣做是為了備份。萬一這個文件系統(tǒng)壞掉了,可以把其他分組保存的文件系統(tǒng)的信息拷貝過來,這樣就完成了文件系統(tǒng)的修復。
文件=內(nèi)容+屬性
注意:Linux的文件屬性和文件內(nèi)容是分批存儲的。
文件屬性存儲在Inode,Inode是固定大小,一個文件一個Inode,記錄文件的幾乎所有屬性,但文件名并不在Inode中存儲!
文件內(nèi)容存儲在data blocks中,隨著應用類型變化,大小也在變化。
Inode為了進行區(qū)分彼此,每一個I弄得都有自己的ID!
ls -li //查看Inode編號
查找一個文件的時候,統(tǒng)一使用的是Inode編號。
先去Inode Bitmap查看這個位置是否被占用,再去Inode屬性里查找block這個數(shù)組,數(shù)組保存文件內(nèi)容保存在data blocks那些數(shù)據(jù)塊中,
下標0-11,直接指向存放數(shù)據(jù)的數(shù)據(jù)塊。
下標12-14,指向的雖然也是一個數(shù)據(jù)塊,但是數(shù)據(jù)塊不光可以保存數(shù)據(jù)也可以保存其他的block id。
這樣大型文件也可以存儲。
刪除文件也是使用Inode
只需要去把Inode Bitmap把該位置1改成0,就去把Block Bitmap把該位置變成0就好了。
但是在Linux下,我們查找,刪除文件都用的是文件名而不是Inode?。?/strong>
問:目錄是文件嗎?
Linux一切皆文件,因此目錄也是文件。
既然是文件就有自己的Inode和date block,Inode放的是目錄的屬性,那數(shù)據(jù)塊里放的是什么?
其實放的是當前目錄下文件名和Inode的映射關系!
因此目錄下創(chuàng)建和刪除文件必須要有寫的權限。
如果有一次誤刪了重要的文件,我該怎么做呢?
最好什么都不要做,如果對其他文件進行了讀寫,Inode會被覆蓋。
想恢復文件怎么做呢?
我們需要知道文件的Inode,去Inode Bitmap把該位置由0變1,然后再去Inode找到數(shù)據(jù)塊的映射關系,根據(jù)映射關系,把Block Bitmap對應的位圖中由0變1,這樣文件內(nèi)容就回來了。
如何知道Inode呢?
我們只知道文件名并不知道Inode,其實OS也考慮到這點,所以OS內(nèi)包含了一個日志信息,當刪除一個文件,OS會把對應刪除的文件與Inode對應關系臨時存儲在日志中,注意這個日志也會有保存時間的。
2.軟硬鏈接
2.1什么是軟硬鏈接
軟鏈接
ln -s myfile.txt soft_file.link
硬鏈接
ln myfile.txt hard_file.link
對軟硬鏈接發(fā)現(xiàn)了什么?
發(fā)現(xiàn)軟鏈接有獨立的Inode,硬鏈接和被鏈接的文件具有相同的Inode。
軟硬鏈接的區(qū)別:是否具有獨立的Inode。
軟鏈接具有獨立的Inode:可以被當作獨立的文件看待。
硬鏈接沒有獨立的Inode,那硬鏈接該如何理解呢?或者建立一個硬鏈接究竟是做了什么?
首先知道,建立硬連接根本沒有創(chuàng)建文件!因為沒有給硬鏈接分配獨立的Inode,既然沒有創(chuàng)建文件,那一定沒有自己的屬性集合和內(nèi)容集合,你用的一定是別人的Inode和內(nèi)容。
這里就回答了:建立硬鏈接就是在指定路徑下,新增文件名和inode的映射關系!
當刪除myfile.txt時,只是將該Inode的映射關系減1。但是Inode還在因此還可以通過hard_file.link與Inode的映射關系找到該文件的內(nèi)容。
那什么時候一個文件算被真正刪除呢?
當一個文件的硬鏈接數(shù)變成0的的時候,這個文件才算真正被刪除!
軟鏈接有自己獨立的Inode和內(nèi)容,當我們刪除myfile.txt,軟鏈接就出錯,但是我們知道Inode還在。
由此可見軟鏈接內(nèi)容保存的不是與文件Inode的映射關系。
其實軟鏈接里面保存的是與文件所處路徑的映射關系。
當把文件刪除時,這個映射關系就出錯了。
軟鏈接其實就相當于windows桌面上的快捷方式。
2.2軟硬鏈接的作用
軟鏈接的應用場景:相對于快捷方式,否則執(zhí)行一個進程需要找到該進程所在路徑才能運行進程,而有了軟鏈接直接運行軟鏈接就可以執(zhí)行當前進程。
unlink soft_file.link //刪除鏈接文件
硬鏈接的應用場景:
一個普通文件創(chuàng)建,硬鏈接數(shù)為1,而創(chuàng)建目錄硬鏈接數(shù)為2,為什么?
一個普通文件,本身就有一個文件名和自己Inode的映射關系。因此為1;
目錄也是一個文件,具有獨立的Inode,首先就有一個映射關系。這是一個硬鏈接。進入目錄之后發(fā)現(xiàn)
.(當前目錄)與新建目錄lesson1的Inode是一樣的。所以當我們執(zhí)行一個進程的時候通常是./a.out其實就相對于lesson1/a.out,(. 也是一個文件名),.就相對于當前目錄lesson1的硬鏈接,因此lesson1的硬鏈接數(shù)為2。
當在lesson1目錄下在創(chuàng)建一個empty目錄,發(fā)現(xiàn)硬鏈接數(shù)由2變成3了。
這是因為,empty目錄下有一個…(上層目錄),這個文件與lesson1的Inode一樣,相對于又是一個硬鏈接,因此lesson1的硬鏈接數(shù)變成3。
Linux為什么不允許普通用戶給目錄創(chuàng)建硬鏈接,而可以創(chuàng)建軟鏈接呢?
其實.和. .不就是給目錄建立的硬鏈接嘛,不過這是由操作系統(tǒng)自己創(chuàng)建的硬鏈接,OS自己弄不怕出錯,而怕用戶創(chuàng)建硬鏈接出錯。
3.動靜態(tài)庫
關于動靜態(tài)庫的知識,在前面【Liunx】開發(fā)工具第5章節(jié)細說了一些內(nèi)容,這里主要是實現(xiàn)動靜態(tài)庫。
靜態(tài)庫(.a結尾):程序在編譯鏈接的時候把庫的代碼鏈接到可執(zhí)行文件中。程序運行的時候?qū)⒉辉傩枰o態(tài)庫。
動態(tài)庫(.so結尾):程序在運行的時候才去鏈接動態(tài)庫的代碼,多個程序共享使用庫的代碼。
3.1什么是庫
程序在經(jīng)過預處理,編譯,匯編,之后,就要鏈接了,鏈接就是將.o文件和庫鏈接起來形成可執(zhí)行程序。
下面我們將演示類似與庫的思想。
問:如果要寫一個庫需要包含main函數(shù)嗎?
其實并不需要,如果庫里面已經(jīng)幫忙寫好了,那我們在main函數(shù)中寫的代碼有什么用呢?
這里創(chuàng)建main函數(shù),主要為了演示代碼的正確性。
首先建立一些文件,寫簡短的add,sub函數(shù)的實現(xiàn)。
gcc -c main.c //形成同名的.o文件
.o文件,是重定位目標二進制文件
現(xiàn)在三個.c文件都已經(jīng)經(jīng)過預處理,編譯,匯編變成了.o文件。下面就該鏈接了。
把所有.o文件鏈接起來有兩種方式
gcc -o mymath main.o my_add.o my_sub.o //直接把.o鏈接起來
gcc -o mymatc main.c my_add.c my_sub.c //先把.c文件形成對于的.o文件,再去鏈接
當所有.o文件鏈接好了,就形成了可執(zhí)行程序。
假如寫庫的人給不想給用庫的人自己的.c文件,那就給用庫的人提供自己的.o可重定位目標二進制目標文件,讓用庫的人來用自己的代碼來進行鏈接就行了。
在預處理階段就報錯了,發(fā)現(xiàn)找不到頭文件,因此我們也把頭文件引入。
這樣編譯就沒報錯了。
下面將所有.o文件鏈接起來
結果是對的。證明編譯是沒問題的。
雖然現(xiàn)在還不懂寫庫,但是未來我可以給對方提供.o文件(方法的實現(xiàn)),.h文件(都有什么方法),然后對方就可以編譯了。------>庫的思想。
.h文件好處理,上面都是沒有經(jīng)過編譯的字符類的,有沒有它能自己看自己查。
但是如果有一萬個.c文件,難道要把這一萬個.c文件都編譯成了.o文件,在加上頭文件一萬個,就有兩萬個文件,就全部直接給用庫的人,那用庫的人在寫命令行的時候是不是太麻煩了。
因此我們可以嘗試將所有的".o文件"打包,給對方提供一個庫文件即可。
庫文件就是多個.o文件打包合并成一個文件,這個文件就是庫,然后打包工具和打包方式的不同就有了動態(tài)庫和靜態(tài)庫。
庫的本質(zhì):就是.o文件的集合。
3.1靜態(tài)庫和靜態(tài)鏈接
生成靜態(tài)庫
ar -rc libmymath.a my_add.o my_sub.o
ar是gnu歸檔工具,rc表示(replace and create)
將my_add.o和my_sub.o歸并到libmymath.a。
交付庫=庫文件.a .so+匹配的頭文件都給別人
.PHONY:output
output:
mkdir -p mylib/include
mkdir -p mylib/lib
cp -f *.a mylib/lib
cp -f *.h mylib/include
寫好庫之后就可以把庫發(fā)布出去了。
tar czf mylib.tgz mylib //打包
然后別人下載,安裝。
cp mylib.tgz ../test //相當于下載
tar xzf mylib.tgz //解壓
上面就用cp已經(jīng)tar命令模仿庫的下載的過程。但是還沒有安裝。
安裝的本質(zhì):就是把對應的軟件安裝到特定的目錄下,就是把它對應的可執(zhí)行程序拷貝到指定的系統(tǒng)能夠找到的目錄。
這里先試試不安裝,直接用。
這里報找不到頭文件的錯誤,但是mylib里面明明就有我的頭文件啊。
其實這是因為,#include"my_add.h" 會在當前路徑下找,但是由于我的庫在mylib目錄下,也就是說不在當前目錄,因此需要指明頭文件在哪。
gcc -o mymath main.c -I./mylib/include //-I指明頭文件
報找不到庫在哪
gcc -o mymath main.c -I./mylib/include -L./mylib/lib
//指明頭文件在哪,指明庫在哪
但是還是報同樣的錯誤,但這次肯定不是找不到庫在哪里了,那這事因為什么呢?
這是因為,如果要鏈接第三方的庫,必須指明庫的名稱。
但我以前寫代碼的時候,從來沒有指明庫的名稱?。?br> gcc —>C
g++ —>C++
編譯器默認可以識別C,C++自帶的庫。
指明了名稱,為什么還有問題?
原因在于,庫名稱不對,
庫名稱:去掉前綴,去掉后綴,剩下的才是庫的名稱。
gcc -o mymath main.c -I./mylib/include -L./mylib/lib -lmymath
查看可執(zhí)行程序依賴的動態(tài)庫列表
ldd mytest
file mytest
發(fā)現(xiàn)我的庫明明是靜態(tài)庫,為什么這里是動態(tài)鏈接?
gcc默認的是動態(tài)鏈接的(建議行為),對于一個特定庫來說,究竟是動態(tài)庫還是靜態(tài)庫,取決于你提供的是動態(tài)庫還是靜態(tài)庫,動態(tài)庫和靜態(tài)庫都給gcc默認是動態(tài)鏈接。
形成一個執(zhí)行成程序,可能不僅僅依賴一個庫。
對于多個庫,gcc也是一個個進行鏈接的。
對于執(zhí)行一個進程,需要再命令行寫一大推的命令,顯得太麻煩了。
我們可以把庫安裝到指定路徑下。
ls /usr/include //頭文件
ls /lib64 //庫文件
sudo cp mylib/include/* /usr/include //安裝頭文件
sudo cp mylib/lib/*.a /lib64 //安裝庫文件
我明明將頭文件和庫文件安裝到指定目錄下了,為什么還報錯?這里肯定是是把相應的文件加載到相應的位置。
還記得上面提過,使用第三方庫要指定庫名稱。
這里加上庫名稱就好了。
刪除
sudo rm /usr/include/my_ *
sudo rm /lib65/libmymath.a
3.2動態(tài)庫和動態(tài)鏈接
生成動態(tài)庫
shared: 表示生成共享庫格式
fPIC:產(chǎn)生位置無關碼(position independent code)
庫名規(guī)則:libxxx.so
位置無關碼,等到動態(tài)庫加載原理細說。
gcc -c -fPIC my_add.c
gcc -c -fPIC my_sub.c
gcc -shared -o libmymath.so my_add.o my_sub.o
這里沒有再像靜態(tài)庫那樣麻煩再打包什么的,而是直接把動態(tài)庫拷貝過去,都是一樣的效果。
gcc -o mymath main.c -I./mylib/include -L./mylib/lib -lmymath
加載共享庫時出錯:libmymath.so:無法打開共享對象文件:沒有這樣的文件或目錄。為什么出現(xiàn)找不到的錯誤?
我不是已經(jīng)告訴庫文件,路徑和庫名稱了嘛。
告訴誰了?
我其實只是告訴gcc了,當把程序編譯完,和gcc還有關系嗎?
和gcc沒有關系了。
程序運行起來,OS和shell也是需要知道庫再哪里的!而自己庫根本沒有在系統(tǒng)指定路徑下,因此OS無法找到。
這里介紹四種解決方法。
3.2.1通過環(huán)境變量找到動態(tài)庫路徑
程序在加載進程時,除了在默認路徑下找,也會在LD_LIBRAY_PATH路徑下找。
echo $LD_LIBRARY_PATH //把路徑信息打印到顯示器
把庫路徑添加到環(huán)境變量里。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wdl/linux/test_10_28/mylib/lib
然后運行就沒問題了。
但是當我重新登錄shell時,發(fā)現(xiàn)又不能運行了。
這是因為我們修改的只是子進程的環(huán)境變量,當子進程退出,在重新登錄shell,如果不對該子進程的環(huán)境變量進行修改,它默認用的是父進程的也就是shell的環(huán)境變量。
3.2.2把動態(tài)庫拷貝到默認路徑下
sudo cp mylib/include/* /usr/include //安裝頭文件
sudo cp mylib/lib/*.so /lib64 //安裝庫文件
3.2.3添加到配置文件中
cd /etc/ld.so.conf.d
這些都是系統(tǒng)默認給我們配置好的文件。
sudo touch lib.conf
sudo vim lib.conf
當配置文件寫好保存退出
發(fā)現(xiàn)還是找不到錯誤,這是因為寫完配置文件需要更新一下。
sudo ldconfig
這樣就沒問題了。
如果要刪除剛才的配置文件,在刪除之后也需要sudo ldconfig更新一下。
3.2.4建立軟鏈接
最簡單的方法就是建立軟鏈接
ln -s /home/wdl/linux/test_10_28/mylib/lib/libmymath.so libmymath.so
在當前目錄下,給我們的庫建立一個軟鏈接,然后運行./mymath可以正確運行,說明在搜索動態(tài)庫的時候,就能夠默認在當前目錄下搜索。
如果不想在當前目錄下建立軟鏈接,就想在系統(tǒng)中可以用它??梢园堰@個軟鏈接建立到對應的系統(tǒng)路徑下。
sudo ln -s /home/wdl/linux/test_10_28/mylib/lib/libmymath.so /lib64/libmymath.so
3.3動靜態(tài)庫的加載原理
3.3.1靜態(tài)庫加載原理
其實靜態(tài)庫并不需要加載,在編譯可執(zhí)行程序的時候,只是把靜態(tài)庫里面的代碼拷貝一份給可執(zhí)行程序,需要一份就拷貝一份,需要多份就拷貝多份。
那把庫代碼拷貝到可執(zhí)行程序的哪里呢?
拷貝到代碼區(qū)??蓤?zhí)行程序文件本身也有邏輯地址,靜態(tài)庫在該文件的代碼區(qū)從0x00000000 到0xffffffff編址。
但是當可執(zhí)行程序加載到內(nèi)存中,這些重復的代碼就造成了內(nèi)存空間的浪費。
靜態(tài)庫是以絕對編制的方式在該文件的代碼區(qū)進行編制的。
3.3.2動態(tài)庫加載原理
靜態(tài)鏈接是將靜態(tài)庫的代碼通過絕對編制的方式拷貝到可執(zhí)行程序的代碼區(qū)。而動態(tài)鏈接是將動態(tài)庫里指定函數(shù)的地址,寫入到我們的可執(zhí)行程序中。
這個地址是偏移地址,就是相對于libc.so(動態(tài)庫)的地址。
假設動態(tài)鏈接調(diào)用的是printf函數(shù),就將printf函數(shù)在動態(tài)庫中的偏移量寫入到可執(zhí)行程序中。
當執(zhí)行到printf時,經(jīng)過頁表讀取時發(fā)現(xiàn)在可執(zhí)行程序中這個這個printf代碼不存在。
但是在編譯的時就在可執(zhí)行程序表明這是一個外部地址,需要訪問動態(tài)庫庫。因此OS先暫停執(zhí)行printf,而先將動態(tài)庫加載到內(nèi)存,然后將庫中的內(nèi)容經(jīng)過頁表映射到進程的共享區(qū)。
動態(tài)庫經(jīng)過頁表映射到共享區(qū),立馬就決定了這個庫的起始地址。
雖然在可執(zhí)行程序中printf語句只是說我們用了那些庫。但是不用擔心,在鏈接的時候,printf中已經(jīng)填寫好了printf在庫的偏移量!
因此當想調(diào)用printf的時候,庫一旦完成了加載,映射的過程之后。想跳轉(zhuǎn)執(zhí)行動態(tài)庫中的方法,直接在自己的上下文中跳轉(zhuǎn)。
庫加載進來,然后就知道了這個庫在共享區(qū)的地址(也是這個庫的起始地址),這時只要拿著printf在鏈接時的形成的printf在庫中的偏移量,再加上這個庫的起始地址,就找到這個代碼在共享區(qū)的地址,然后去調(diào)用這個函數(shù),調(diào)用結束之后,再返回代碼處向后繼續(xù)執(zhí)行。
文章來源:http://www.zghlxwxcb.cn/news/detail-727746.html
這就是動態(tài)庫訪問,加載的過程。文章來源地址http://www.zghlxwxcb.cn/news/detail-727746.html
到了這里,關于【linux】文件系統(tǒng)+軟硬連接+動靜態(tài)庫的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!