文章目錄
- 1.動態鏈接庫簡介
- 2.動態庫搜索路徑
- 3.運行時鏈接及搜索順序
- 4.查看可運行模塊的鏈接庫
- 5.總結
1.動態鏈接庫簡介
動態庫又叫動態鏈接庫,是程序運行的時候加載的庫,當動態鏈接庫正確安裝后,所有的程序都可以使用動態庫來運行程序。動態庫是目標文件的集合,目標文件在動態庫中的組織方式是按特殊的方式組織形成的。在動態庫中函數和變量的地址是相對地址而不是絕對地址,其真實地址在調用動態庫的程序加載時形成的。
動態庫的名字有別名(soname), 真名(realname)和鏈接名(linkername)。別名是由一個lib前綴,然后是庫的名字,最后以“.so”結尾來構成。真名是動態鏈接庫的真實名字,一般總是在別名的基礎上添加一個版本號信息。除此之外還有一個鏈接名,他是在程序鏈接的時候使用的名字。
動態庫安裝的時候,總是復制庫文件到某一個目錄,然后使用一個軟鏈接生成一個別名,在庫文件更新的時候,僅僅更新軟鏈接即可。
2.動態庫搜索路徑
(僅對ELF格式)如果可執行文件包含DT_RPATH標簽,并且不包含DT_RUNPATH標簽,將從DT_RPATH列出的路徑搜索。(DT_RPATH已經被廢棄,請用DT_RUNPATH)
如果LD_LIBRARY_PATH在程序運行時被定義,那么將從它包含的路徑開始。安全起見,對于set-user-ID或者set-group-ID的程序,這個變量將被忽略。
(僅對ELF格式)如果可執行文件包含DT_RUNPATH標簽,將從這個標簽列出的路徑開始搜索。
從 /etc/ld.so.cache(運行ldconfig產生)中查找文件
從/lib以及/urs/lib,按順序搜索。如果鏈接時指定-z nodefaultlib,這個步驟將被忽略。
3.運行時鏈接及搜索順序
這個過程是由ld-linux.so程序來執行,這個才是真正的鏈接。它所做的工作就是將動態庫的代碼映射到進程的虛擬地址空間中,供進程來調用。程序在連接時使用了共享庫,就必須在運行的時候能夠找到共享庫的位置。linux的可執行程序在執行的時候默認是先搜索/lib和/usr/lib這兩個目錄,然后按照/etc/ld.so.conf里面的配置搜索絕對路徑。同時,Linux也提供了環境變量LD_LIBRARY_PATH供用戶選擇使用,用戶可以通過設定它來查找除默認路徑之外的其他路徑,LD_LIBRARY_PATH路徑優先于系統默認路徑之前查找。
LD_LIBRARY_PATH的設定作用是全局的,過多的使用可能會影響到其他應用程序的運行,所以多用在調試。通常情況下推薦還是使用gcc的-R或-rpath選項來在編譯時就指定庫的查找路徑,并且該庫的路徑信息保存在可執行文件中,運行時它會直接到該路徑查找庫,避免了使用LD_LIBRARY_PATH環境變量查找!!(看到Qt的使用qmake生成的makefile中,有gcc -rpath xxx,指出程序運行時的一個搜索路徑, 或許與qt的QMAKE_RPATHDIR有關)
ld-linux.so.x在可執行的目標文件中被指定,可用readelf -l命令查看 。
(很多現代應用都是通過動態編譯鏈接的,當一個 需要動態鏈接 的應用被操作系統加載時,系統必須要 定位 然后 加載它所 需要的所有動態庫文件。 在Linux環境下,這項工作是由ld-linux.so.x來負責完成的)
和Windows下的PE文件類似,ELF文件是linux系統下可執行文件、動態庫文件、靜態庫文件的標準格式。
例如,運行readelf -l 文件名,在輸出的Headers部分的INTERP部分,會指出該可執行文件需要的ld-linux.so。
運行時,ld-linux.so 查找共享庫的路徑:
(1)編譯時使用gcc的-R或-rpath選項指定路徑。
(2)LD_LIBRARY_PATH環境變量中所設定的路徑。
(3)ld-linux.so 缺省在/usr/lib和/lib中搜索;當glibc安裝到/usr/local下時,它查找/usr/local/lib
(4)/etc/ld.so.conf(或/usr/local/etc/ld.so.conf)中所指定的路徑。 (查看/etc/ld.so.conf文件:或許只有一行:“include /etc/ld.so.conf.d/*.conf ”,意味著包括了/etc/ld.so.conf.d/目錄下的所有.conf文件,每個文件中都寫著具體的路徑。如果你想加一個運行時的搜索路徑,可在/etc/ld.so.conf.d目錄下新建一個.conf文件,里面寫上路徑,注意添加完了之后要在root權限下運行ldconfig指令,使其生效,該指令更新記錄了系統中有哪些so文件的緩存文件(/etc /ld.so.cache)。)
4.查看可運行模塊的鏈接庫
可使用ldd指令查看一個可執行文件依賴于哪些庫:ldd xxx
ldd bash
linux-vdso.so.1是Linux為了解決和glibc兼容而想出的絕招。
原來這個 linux-vdso.so.1 文件,并不是一個真實存在的文件,而是 Linux 中的一個虛擬文件,專門用于將內核中一些常用的函數從內核空間映射到用戶空間。也就是說,這個文件不用復制。
VDSO就是Virtual Dynamic Shared Object,就是內核提供的虛擬的.so,這個.so文件不在磁盤上,而是在內核里。內核把包含某.so的內存頁在程序啟動的時候映射入其內存空間,對應的程序就可以當普通的.so來使用其提供的函數接口。
5.總結
在linux下的動態鏈接庫并不從程序所在當前目錄查找連接庫,而是從編譯時指定目錄查找,或者默認目錄查找。