2013-04-11 33 views
4

我認爲Linux中的一個主要設計缺陷是共享對象地獄,當涉及到分發程序而不是源代碼形式。在運行時加載Linux庫

這裏是我的具體問題:我想發佈一個ELF二進制形式的Linux程序,它應該儘可能多地運行在發佈版本上,所以我的強制性依賴性如此低:在任何情況下所需的唯一庫是libpthread ,libX11,librt和libm(當然還有glibc)。當我使用gcc構建我的程序時,我正在動態鏈接這些庫。

但是,我的程序還應該支持ALSA(聲音接口),Xcursor,Xfixes和Xxf86vm擴展以及GTK。但是這些只能在用戶系統上可用時使用,否則我的程序仍應運行,但功能有限。例如,如果GTK不在那裏,我的程序將回退到終端模式。因爲我的程序仍然可以在沒有ALSA,Xcursor,Xfixes等的情況下運行,所以我不能動態鏈接這些庫,因爲如果其中一個庫不存在,那麼程序根本無法啓動。

所以我需要手動檢查庫是否存在,然後使用dlopen()逐個打開它們,並使用dlsym()導入必要的函數符號。然而,這會導致各種問題:

1)庫命名約定: 共享對象往往不是簡單地稱爲「libXcursor.so」,但有某種版本的擴展,如「libXcursor.so的。 1「,甚至像」libXcursor.so.0.2000「這樣的非常有趣的東西。這些擴展名似乎因系統而異。所以在調用dlopen()時應該選擇哪一個?在這裏使用硬編碼名稱似乎是一個非常糟糕的主意,因爲名稱因系統而異。因此,我想到的唯一解決方法是掃描整個庫路徑並查找以「libXcursor.so」前綴開頭的文件名,然後執行一些自定義版本匹配。但我怎麼知道他們真的兼容?

2)庫搜索路徑:我應該在哪裏查找* .so文件?這也是不同的系統。有一些默認路徑,如/ usr/lib和/ lib,但* .so文件也可能在很多其他路徑中。所以我必須打開/etc/ld.so.conf並解析它以找出所有庫搜索路徑。這並不是一件小事,因爲/etc/ld.so.conf文件也可以使用某種包括指令,這意味着我必須解析更多的.conf文件,對由循環引起的可能的無限循環進行一些檢查包括指令等。真的沒有更簡單的方法來找出* .so的搜索路徑嗎?

所以,我的實際問題是:是不是有一種更方便,不太方便的方式來實現我想要做的事情?創建一個有ALSA,GTK,libXcursor等一些可選依賴項的Linux程序真的很複雜......但是如果沒有它,它也應該可以工作!有什麼樣的標準去做我想做的事情?還是我註定要做這種駭人的方式?

感謝您的意見/解決方案!

+0

您是否考慮構建自己的共享庫?這些可以與您需要的系統庫動態鏈接,可以在您期望的位置,並且可以知道您的名字。 – Hasturkun 2013-04-11 15:22:37

+0

此外,你可能想看看這個問題:http://stackoverflow.com/questions/2827181/dynamic-loading-of-shared-objects-using-dlopen?rq=1 – Hasturkun 2013-04-11 15:38:27

+0

@ 1:對,這可能是一個解決方法,但我必須分發我的應用程序伴隨* .so文件。我希望在我的發行版中只有一個ELF二進制文件。 – Andreas 2013-04-11 15:47:43

回答

2

我認爲Linux中的一個主要設計缺陷是共享對象地獄,當涉及到分發程序而不是源代碼形式。

就係統的創造者而言,這不是一個設計缺陷;這是一個優勢 - 它鼓勵你以源代碼的形式發佈程序。哦,你想賣你的軟件?對不起,這不是Linux優化的用例。

庫命名約定:共享的對象往往不是簡單地稱爲「libXcursor.so」,但有某種版本的擴展,如「libXcursor.so.1」甚至真的很有趣的東西,如「libXcursor.so.0.2000 」。

是的,這就是所謂的外部庫版本。閱讀關於它here。從描述中應該清楚,如果您在系統上使用頭文件編譯二進制文件,那麼通常會給您提供libXcursor.so.1作爲運行時參考,那麼您與之兼容的只有共享庫是libXcursor.so.1,並且會嘗試到dlopenlibXcursor.so.0.2000將導致到不可預知的崩潰。

任何提供libXcursor.so但不是libXcursor.so.1的系統都是破損的安裝,或者也與您的二進制文件不兼容。

圖書館搜索路徑:我應該在哪裏尋找* .so文件?

不應該試圖使用他們的完整路徑dlopen這些庫中的任何一個。只需調用dlopen("libXcursor.so.1", RTLD_GLOBAL);,運行時加載程序將在系統適當的位置搜索庫。

+0

感謝您的澄清!我現在正在使用dlopen()中的共享對象的SONAME。 – Andreas 2013-04-16 19:56:58