linux 編譯查看鏈接庫詳情,Linux環境下的編譯,鏈接與庫的使用

鏈接參數控制

鏈接器中提供了-dn -dy 參數來控制使用的是動態庫還是靜態庫,-dn表示后面使用的是靜態庫,-dy表示使用的是動態庫

例:

g++ -Lpath -Wl,-dn -lx -Wl,-dy -lpthread 這樣如果在path路徑下有libx.so和libx.a這個時候只會用到 libx.a.

注意在最后的地方如果沒有-Wl,-dy 讓后面的庫都使用動態庫,可能會報出 “cannot find -lgcc_s” 的錯誤,這是由于glibc的.a庫和.so庫名字不同,–static會自動處理,但是 -Wl,-dy卻不會去識別這個問題.

小提示:

如果使用–static, 由于-dy的使用導致后面的庫都是共享庫(dy強制屏蔽了靜態庫),這個時候編譯出來的程序和只有動態庫的情況下強制使用–static編譯一樣都會報錯

運行報錯 ”undefined reference to `xxx()’ ” 對 于動態鏈接庫,實際的符號定位是在運行期進行的.在編譯.so的時候,如果沒有把它需要的庫和他一起進行聯編,比如libx.so 需要使用uldict, 但是忘記在編譯libx.so的時候加上-luldict的話,在編譯libx.so的時候不會報錯,因為這個時候libx.so被認為是一個庫,它里面 存在一些不知道具體實現的符號是合法的,是可以在運行期指定或者編譯另外的二進制程序的時候指定.

如果是采用 g++ -Lpath -lx 的方式進行編譯,鏈接器會發現所需要的uldict的符號表找不到從而報錯,但是如果是程序采用dlopen的方式載入,由于是運行期,這個程序在這個地 方就直接運行報錯了. 另外還有一種情況就是一個對外的接口在動態庫中已經聲明定義了,但是忘記實現了,這個時候也會產生類似的錯誤.

如果在運行期報出這樣的錯誤,就要注意是否是由于某些庫沒有鏈接進來或者某些接口沒有實現的原因產生

日志庫問題 其實不只是日志庫存在這樣的問題,其他需要同時被多個動態庫以及主程序同時使用的函數其實都存在這樣的問題.這里主要以日志庫的問題為例來說明這些問題.

有 一個程序,它通過dlopen的方式調用了一個.so文件. 在這個主程序中和.so中都使用了日志庫,主程序中使用ul_openlog打開了日志, 在.so中沒有用ul_openlog打開日志.這個時候發現,主程序中的日志正常輸出,但.so中的日志卻直接輸出到了標準出錯.

這個問 題的原因在前面的其實已經提到了,在默認情況下主程序中使用的接口對于.so是不可見的,.so所在的代碼空間與主程序的代碼空間是隔離的,這個時 候.so調用的ul_writelog其實是沒有經過ul_openlog的那塊代碼空間,由于ul_log庫使用了一些static變量(如果是帶 comlog的ul_openlog那還有全局符號),只有在ul_writelog, ul_openlog都是在同一塊空間上的時候才會起作用.

這個問題的一個最簡單的解決方案是

在主程序的鏈接的時候加入-rdynamic,仍然鏈接libullib.a庫 編譯動態鏈接庫時,不加鏈接libullib.a庫 其實動態庫這里是否鏈了libullib.a已經不重要了,在有-rdynamic的情況下,.so中如果有與主程序同名的函數那么會優先調用主程序中的函數, 動態庫不鏈接libullib.a倒是可以省點空間

但是這種方式在某些情況還是不能完全解決問題

假 設有A.so, B.so,主程序main, 在A.so中調用了ul_openlog, B.so中沒有調用ul_openlog, 但調用了ul_writelog. 在主程序中沒有調用ul_log中的任何接口和使用任何變量.這種情況下即時使用了-rdynamic還是會導致在 A.so中正常輸出日志,但在B.so中卻把日志輸出到標準出錯.

這個問題的主要原因在于,gcc在鏈接的時候是以.o為單位的,如果一 個.o中的符號沒有被外部所使用,那么在鏈接的時候就不會把這個.o中的符號給鏈接進行.so或者二進制程序中.在上面的問題中主程序里面沒有調用到日志 庫中的任何符號,所以在鏈接的時候就不會把ullib中的ul_openglog和ul_writelog給鏈接進行主程序中,這個時候即使有 -rdynamic也是做不到讓.so中的動態鏈接庫都使用.

這個問題一般有下面幾種方案:

載入A.so的時候使用RTLD_GLOBAL參數,把A.so中的所有的符號都變成對外可見,這樣A.so和B.so的ul_writelog都在一塊代碼空間中了 編譯主程序的時候鏈接ullib的地方由-lullib改為 -Wl,–whole-archive -lullib -Wl,–no-whole-archive, 同時加上-rdynamic. -Wl, –whole-archive是鏈接參數,它表示把ullib的中所有的符號都鏈接進主程序中,而不管主程序是否調用了ullib中的符 號.-Wl,–no-whole-archive表示后面的鏈接取消–whole-archive的行為,畢竟其他的庫沒有必要采用這種方式全部鏈接 進來. 在主程序中隨便調一下ul_log中的符號,比如可以先隨便ul_openlog一下,然后ul_closelog, 后面再進行動態庫調用. 把libullib.a用 ar x 命令還原成多個.o文件,采用直接鏈接的方式使用ul_log.o. 上 面的幾個問題的產生主要還在于靜態鏈接和動態鏈接混用,而兩種鏈接方式又存在不一樣的地方.事實上如果我們把ullib庫 采用動態鏈接庫的方式編譯成 libullib.so, 采用前面的方式在編譯期鏈接libullib.so,并且設置LD_LIBRARY_PATH, 上面的2個問題都不會存在. 編譯期使用的.so,是全局可見的,不需要-rdynamic也可以被dlopen的動態庫所用到,由于是動態鏈接庫,所以 包含了所有的符號,不會像靜態庫那樣只包含了所用到的.o中的符號. 事實上這也是多數第三方程序的解決方案

主程序中使用-rdynamic會對后續的升級造成一些麻煩:

加上-rdynamic后,像日志庫這樣的基礎如果需要升級, 那么就必須要升級主程序, 使用的.so無論如何升級所用到的ul_writelog都是主程序中的. 主程序中除了日志庫,還會有其他庫或者函數的存在, 這些函數如果不是static的就有可能與 dlopen打開的so中的函數混到一起,造成困惑 如果.so中需要打印它自己的日志, 那樣需要comlog本身功能的支持才可以實現,而不能簡單的使用ul_writelog來實現 但是如果主程序中沒有使用-rdynamic,那么又有下面的這些麻煩 dlopen打開的動態庫日志是打印自己的, 不能和主程序統一在一起. 如果.so的程序和主程序open的是同一個日志,這相當于多進程打日志, 那必須要comlog的支持,ullog本身不支持多進程打同一個日志. 如果主程序中用dlopen+RTLD_GLOBAL的打開了某個.so 日志的問題就可能影響到其他的.so中的調用. 同時對于一些老程序, 升級前后-rdynamic 可能也會產生影響,比如兩次ul_openlog 這里對于類似日志庫這種需要全局狀態變量支持的庫提出另外方案

編譯一個專門的.so, 這個.so中包括了其它.so中所需要的所有和全局量相關的接口 2. 主程序不使用-rdynamic編譯, 但打開上面的.so的時候,采用RTLD_GLOBAL方式,并且是第一個打開 3. 除了打開第一個 .so, 其它的.so都不使用RTLD_GLOBAL方式, 并且在編譯的時候都不把和第一.so相關的庫聯編 4. 第一個.so的升級需要保證沒有其它.so在運行才可以dlclose, 重新dlopen

這個問題首先需要明確需求, 到底是希望每個.so打自己獨立的日志,還是和主線程統一

這 里要注意另外一個問題就是目前的ullib 日志庫情況比老的ullog要復雜, 在comlog中引入一些extern 出來的全局變量 在采用dlopen的時候,對于一般符號,一般都是主程序和動態庫在兩塊空間中, 但是對于使用extern出來的變量主程序和動態庫都是在一塊空間中(注:由于32位下不用-fPIC也可以編譯so, 在沒有-fPIC的情況也是分開的, 但是由于64位一定要-fPIC所以一定會出現同一塊空間的問題), 對于這個問題的解決方案是在動態庫鏈接的時候加上 -Wl,-Bsymbolic 參數將動態庫的空間和主程序的空間強行分開。

上面有提到 編譯動態鏈接庫時,不加鏈接libullib.a庫,但主程序使用-rdynamic, 這里主要是為了避免使用到了不同的ullib導致調用了一些不同的內部符號,導致出現另外的麻煩

對于動態庫中的日志建議采用下面的幾個方案:

動態庫完全打自己的,日志,編譯二進制程序不要用-rdynamic, 動態庫鏈接的編譯加上 -Wl,-Bsymbolic 參數 , 鏈接ullib, 在動態庫中自己open,自己控制等級 1. 動態庫不鏈接ullib, 編譯二進制程序用-rdynamic , 這樣可以正確的使用主程序中的日志庫,也規避了版本不一致帶來的問題, 但是這樣失去了對于動態庫日志的控制, 而且存在升級的不便, 日志的升級是由主程序控制的。

小提示:

有關動態庫使用的例子還可以參考 SoTips 在運行期可以通過設置環境變量LD_DEBUG查看每個符號具體鏈接到了什么地方,每個符號具體的查找過程和綁定過程.可以這樣使用 export LD_DEBUG=help 隨便運行一個程序就可以看到對于LD_DEBUG的使用說明

export LD_DEBUG=files./main 可以看到整個裝載過程

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458942.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458942.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458942.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在C++中用虛函數的作用是什么? 為什么要用到虛函數?

***************************************************更多精彩,歡迎進入:http://shop115376623.taobao.com***************************************************虛函數聯系到多態,多態聯系到繼承。所以本文中都是在繼承層次上做文章。沒了繼…

mysql 主主互備實現

今天星期天,么事就寫個MYSQL的主主架構的博客,原理如下圖,不是我畫的網上找的。主機作用操作系統mysql版本對應IPvip數據庫mysqlA(主)centos6.4mysql 5.5.48192.168.48.129192.168.48.126mysqlB(備)centos6.4mysql 5.5.48192.168.48.132一&am…

Linux Deepin 版本大全,Deepin下載-Deepin linuxv20.0 官方版下載-6188手游網

Deepin linux安裝準備一:為 Deepin 留出硬盤空間以便安裝。1.打開磁盤管理(Windows 徽標上右鍵單擊,選擇磁盤管理)。2.選中一個分區(空閑空間大于 30G),我選擇的是 C 盤,因為是固態硬盤所以安裝啟動會快很多。磁盤 1 的 200G 分區…

動手實踐 Linux VLAN - 每天5分鐘玩轉 OpenStack(13)

本節我們來看如何在實驗環境中實施和配置如下 VLAN 網絡 配置 VLAN 編輯 /etc/network/interfaces,配置 eth0.10、brvlan10、eth0.20 和 brvlan20。 下面用 vmdiff 展示了對 /etc/network/interfaces 的修改 重啟宿主機,ifconfig 各個網絡接口 用 brct…

Socket的3次握手鏈接與4次斷開握手

*************************************************** 更多精彩,歡迎進入:http://shop115376623.taobao.com *************************************************** 連接握手: 1.客戶端發送建立連接請求 (發送請求)2.…

Linux桌面需要強制訪問控制,RHCSA 系列(十三): 在 RHEL 7 中使用 SELinux 進行強制訪問控制...

RHCSA 認證:SELinux 精要和控制文件系統的訪問盡管作為第一級別的權限和訪問控制機制是必要的,但它們同樣有一些局限,而這些局限則可以由安全增強 Linux(Security Enhanced Linux,簡稱為 SELinux)來處理。這些局限的一種情形是&am…

使用canvas實現擦玻璃效果

體驗效果:http://hovertree.com/texiao/html5/25/效果圖&#xff1a;代碼如下&#xff1a; <!DOCTYPE html> <html> <head lang"zh"> <meta name"viewport" content"initial-scale1.0, maximum-scale1.0, user-scalableno, widt…

如何計算時間復雜度

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 求解算法的時間復雜度的具體步驟是&#xff1a; ⑴ 找出算法中的基本語句&#xff1b;…

linux顯示系統信息軟件下載,linux查看系統信息軟件安裝信息命令學習筆記

查看LINUX安裝版本[rootlocalhost etc]# unameLinux[rootlocalhost etc]# uname -aLinux localhost.localdomain 2.6.32-279.11.1.el6.i686 #1 SMP Tue Oct 16 14:40:53 UTC 2012 i686 i686 i386 GNU/Linux[rootlocalhost etc]# cat /proc/versionLinux version 2.6.32-279.11.…

Bzoj 2662: [BeiJing wc2012]凍結 dijkstra,堆,分層圖,最短路

2662: [BeiJing wc2012]凍結 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 647 Solved: 348[Submit][Status][Discuss]Description “我要成為魔法少女&#xff01;” “那么&#xff0c;以靈魂為代價&#xff0c;你希望得到什么&#xff1f;” “我要將有關魔法和奇…

[轉]opencv學習資料

轉自&#xff1a;http://blog.csdn.net/poem_qianmo/article/details/20537737 1&#xff1a;Mat imread(const string& filename, intflags1 ); eg: Mat image0imread("dota.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);//載入最真實的圖像 ge1i…

linux servlet 亂碼問題,Servlet一次亂碼排查后的總結

由來在寫一個小小的表單提交功能的時候&#xff0c;出現了亂碼&#xff0c;很奇怪request上來的參數全部是亂碼&#xff0c;而從數據庫查詢出來的中文顯示到頁面正常&#xff0c;鎖定肯定是request對象那里出了問題。后來經過排查&#xff0c;發現是我封裝的框架中出了問題&…

C/C++回調函數

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 對于很多初學者來說&#xff0c;往往覺得回調函數很神秘&#xff0c;很想知道回調函數…

Linux 命令[2]:mkdir

make directories mkdir -p [目錄名] -p 遞歸創建 [rootlocalhost ~]# mkdir -p test [rootlocalhost ~]# ls anaconda-ks.cfg install.log install.log.syslog test 當然只創建一個目錄 -p 是可以省略的 注&#xff1a;如果創建多級目錄沒有 -p 會報錯 如&#xff1a; [roo…

jQuery動態設置樣式List item

前段時間&#xff0c;Insus.NET有修改一個功能《激活當前視圖菜單高亮呈現》http://www.cnblogs.com/insus/p/5287093.html 今天Insus.NET想改用另外一個方法來實現&#xff0c;使用jQuery。在ASP.NET MVC 環境實現&#xff1a; 代碼&#xff1a; <ul><li><a hr…

linux telnet 權限,允許telnet 通過root用戶進行訪問

允許telnet 通過root用戶進行訪問RHEL6:[rootclovem ~]# yum install telnet-server -y //安裝telnet服務端[rootclovem ~]# cat /etc/xinetd.d/telnet //開啟telnet的托管服務# default: on# description: The telnet server serves telnet sessions; it uses \#unencrypt…

TOUGHRADIUS 項目介紹

2019獨角獸企業重金招聘Python工程師標準>>> TOUGHRADIUS 項目介紹 ToughRADIUS是一個開源的Radius服務軟件&#xff0c;采用于 Apache License 2.0 許可協議發布&#xff0c;從創立之日起&#xff0c;他的宗旨就是服務于中小微ISP&#xff0c;讓運營變得更簡單。 T…

轉:Jmeter 用戶思考時間(User think time),定時器,和代理服務器(proxy server)...

在負載測試中需要考慮的的一個重要要素是思考時間&#xff08;think time&#xff09;&#xff0c; 也就是在兩次成功的訪問請求之間的暫停時間。 有多種情形揮發導致延遲的發生&#xff1a; 用戶需要時間閱讀文字內容&#xff0c;或者填表&#xff0c;或者查找正確的鏈接等。未…

linux sql語句傳參數,Linux/Unixshell參數傳遞到SQL腳本

在數據庫運維的過程中&#xff0c;Shell 腳本在很大程度上為運維提供了極大的便利性。而shell 腳本參數作為變量傳遞給SQL以及SQL腳本也是DB在數據庫運維的過程中&#xff0c;Shell 腳本在很大程度上為運維提供了極大的便利性。而shell 腳本參數作為變量傳遞給SQL以及SQL腳本也…

Myeclipse5.5獲取注冊碼

2019獨角獸企業重金招聘Python工程師標準>>> import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class MyEclipseGen {private static final String LL "Decompiling this copyrighted software is a vi…