linux 動態裝載動態庫 ldd,ldconfig,ld.so.conf, ld.so.cache
前面我們介紹過,GCC編譯C++程序的那些步驟,其中包括編譯的時候include的搜索目錄,鏈接的時候庫的搜索目錄(這裡的庫包含兩種庫)。還有一個時候,需要搜索路徑,那就是裝載動態庫的時候,這個時候與GCC無關了。而是與Linux系統自身有關係。
動態轉載動態庫,是為基於動態庫編譯鏈接而來的可執行程序設定的一個程序執行過程中需要的功能,對於那些只基於靜態庫的可執行程序來說,這個功能沒有什麼用。
1)執行這個動作的linux程序: ld.so
2)這個程序參考的文件為:/etc/ld.so.conf,該文件保存著ld應該搜索的so文件路徑。通常ld.so.conf.d這個文件夾下也保存著分文件,以供合成ld.so.conf
3)該程序實際參考的文件為:/etc/ld.so.cache.這個文件會其實基本上就是對/etc/ld.so.cache 做了稍微的處理利於/usr/bin/ld程序的參考。
4)將/etc/ld.so.conf 更新到/etc/ld.so.cache.的命令: ldconfig. 使用 ldconfig -p|less可以逐步查看從/usr/bin/ld 眼裡的/etc/ld.so.cache的內容(路徑)。
5)所以往/etc/ld.so.conf內做指定的路徑,如/usr/lib等加入你需要程序搜索的動態庫.so文件,不需要執行ldconfig更新。因為/etc/ld.so.cache中保存的就是目錄,而不是具體的so文件。
6)向/etc/ld.so.conf添加路徑。則需要調用ldconfig來更新/usr/bin/ld的搜索路徑。
ld可以叫靜態連接器,ld.so可以叫動態連接器
運行時動態庫的搜索路徑: 動態庫的搜索路徑搜索的先後順序是
①編譯目標代碼時指定的動態庫搜索路徑(這是通過gcc 的參數"-Wl,-rpath,"指定。當指定多個動態庫搜索路徑時,路徑之間用冒號":"分隔)
②環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑(當通過該環境變量指定多個動態庫搜索路徑時,路徑之間用冒號":"分隔)
③配置文件/etc/ld.so.conf中指定的動態庫搜索路徑;
④默認的動態庫搜索路徑/lib;
⑤默認的動態庫搜索路徑/usr/lib。
也就是說,雖然linux以裝載動態庫時搜索的路徑以/etc/ld.so.conf為主,但是,仍然有其它的方式,來構建這種裝載路徑的靈活性。仍然是遵守那種先「專」後「寬」的模式去縮短可能的搜索時間。 第一個,就是在編譯連接該程序的時候,就指定將來需要動態庫的時候搜索的位置。注意這個與當時的鏈接路徑雖然有很大的關係,但是他們的概念是不同的。 第二個,也就是在使用/etc/ld.so.conf之前,還有一個路徑設置方法就是環境變量LD_LIBRARY_PATH. 這個東西可以使用:
# export LD_LIBRARY_PATH=」/usr/lib/old:/opt/lib 來創建修改這個變量。
第三個,才是/etc/ld.so.conf 最後。則是系統默認路徑。
(2) 靜態鏈接庫和動態鏈接庫的使用區別
首先,回顧一點,一個程序,從源代碼到運行,包括:編譯(compile)、鏈接(link)、加載(load)、運行(execute),對應的GNU工具一般為:編譯器compiler(gcc)、鏈接器linker(ld)、加載器loader(其中動態鏈接庫加載器為ld.so(ld-linux.version.so),在/lib目錄中,如 /lib/ld-linux.so.2,所以不能直接在命令行下運行ld-linux.so,需要完整路徑,加載器一般不需要我們直接運行,在運行可執行程序的加載過程中包含有動態加載的過程)。經常會將編譯和鏈接統稱為編譯,期間為編譯時(compile time);而加載和運行統稱為運行,期間為運行時或執行時(runtime/execution time)。
靜態鏈接庫:
編譯時(compile time)被使用(更詳細的是鏈接的時候)。在鏈接靜態庫的時候,鏈接器會在其中找到所需要鏈接的函數,然後將它們拷貝到執行文件,這種拷貝是完整的拷貝,所以在鏈接成功後,程序運行不需要靜態庫的參與。
動態鏈接庫:
編譯時和運行時都被使用。在編譯時,鏈接器在其中找到所需要的函數(或其他對象文件),生成地址/位置無關代碼(Position Independent Code (PIC)),並沒有真正的實現拷貝;在運行時(runtime/execution-time),某個程序在運行中要調用某個動態鏈接庫函數的時候,操作系統首先會查看所有正在運行的程序,看在內存裡是否已有此庫函數的拷貝了,如果有,則讓其共享那一個拷貝;只有沒有才鏈接載入
。
說明:Linux下進行鏈接的缺省操作是先考慮動態鏈接庫,即如果同時存在靜態和動態庫,不特別指定的話,將與動態庫相連接。