so库方法原理
動態庫
So庫,又動態名庫,是Linux下最常見的文件之一,是一種ELF文件。這種so庫是程序運行時,才會將這些需要的代碼拷貝到對應的內存中。但程序運行時,這些地址早已經確定,那程序引用so庫中的這些代碼地址如何確定呢,這就是這次要整理學習的內容,即so庫的在鏈接和執行時的加載過程。

靜動態庫
先聊靜態庫。為了程序更加優雅和高效,每一個程序的完成都是采用分而治之的方法,即同一個程序或者項目每個程序員都會完成不同的功能,有的功能是可復用的,而對于一些公共的可復用的功能,會使用庫的形式來完成。比如我們在不同模塊中多次用到了一個方法ar_public(),我們就可以將其包裝到一個公共的文件里面,這樣就如果其他的地方有調用就可以把引用這個公共文件從而調用這個方法,這樣就有了靜態庫。簡單來說靜態庫是鏈接的時候將庫中所用到的程序拷貝進來,這樣即使在執行階段吧對應的庫刪掉都沒有關系,因為此時對應方法的真實內容已經被拷貝過來了。但是雖然能做到方法共用,但帶來最大的一個問題是如果是同一個項目的不同模塊使用的話,使用的每個模塊都會把這些拷貝過來,這樣會使得應用的內存增大。也恰恰是由于會將靜態庫的這些方法拷貝進來如果靜態庫發生改變的話那程序需要重新編譯。
為了解決上面的問題,于是又有了一個動態庫的概念。動態庫,又稱共享庫鏈接的時候它只包含需要的函數引用表,只有在執行的時候那些需要的函數才能被拷貝到內存中,而且在操作系統使用的是虛擬內存,使得一份共享庫駐留在內存中被多個程序使用,也同時節約了內存。
位置無關(PIC)
大家都知道,可執行文件在執行期的時候內存地址已經都確定了,而上面說的只有執行時才會確定那些函數地址拷貝到內存中,那基于這個特點大家第一想道的實現就是像那些段一樣預留一個空間,但是這樣做的一個最大問題就是會造成空間浪費,我們可以readelf去看下so庫中的地址情況,從圖一來看和data相關的地址都不是絕對地址(由于程序的起始加載地址都是從data開始,所以data相關的頭如果不是絕對地址則可以認為加載的地址不固定)。
在動態共享庫中,如果庫里面的代碼發生改變,重新加載進來之后,我們必須保證它放到修改前的位置 ,否則我們還要為它找一個新的位置。而我們對于這個修改之后希望將動態庫編譯成可以在任意位置加載無需linker進行修改,這個叫做位置無關代碼即PIC,也就是生成so庫的-fPIC的那個PIC(這個指令就表示生成位置無關代碼)。那PIC的原理是如何實現的呢,我們都知道數據段和代碼段的距離在運行時是可以確定的,其中就是利用這一點來做地址定位的。
靜態分析:
Linux Dynamic Shared Library && LD Linker
https://www.cnblogs.com/cdcode/p/5551649.html
動態鏈接
聊聊Linux動態鏈接中的PLT和GOT(1)——何謂PLT與GOT
_dl_runtime_resolve源碼分析
【ARM】安卓SO中GOT REL PLT 作用與關系
深入了解GOT,PLT和動態鏈接
總結
- 上一篇: 走到了尽头是什么歌呢
- 下一篇: cmake生成so包并调用(C++pro