2012-09-13 48 views
2

我有三樣東西:開源應用程序(我們稱之爲APP), 封閉源代碼的共享庫(姑且稱之爲OPENGL) 和開源插件OPENGL(讓我們稱之爲PLUGIN)[也是共享庫]。
操作系統:Linux。

需要在APP和PLUGIN之間共享數據, 這樣APP與PLUGIN連接,當我運行它時, 系統會自動加載它。

之後,APP調用屬於OPENGL的eglInitialize, ,之後該函數再次加載PLUGIN。

之後我在APP內存中有兩個PLUGIN副本。

我知道,因爲PLUGIN有全局數據,並且經過調試 我看到有兩個全局數據副本。

所以問我如何解決這個問題? 我想要一個由APP和OPENGL使用的PLUGIN實例。 我無法更改OPENGL庫。dlopen的和隱性的庫加載:同一庫的兩個副本

回答

1

我懷疑OPENGL正在加載帶有RTLD_LOCAL標誌的PLUGIN。這個 通常是你在加載插件時想要的,所以多個插件不會衝突。

我們在Java下加載代碼時遇到了類似的問題:我們會加載一個 左右的不同模塊,並且它們不能與另一個 進行通信。我們的解決方案可能適用於您:我們爲插件編寫了一個 包裝器,並告訴Java包裝器是插件。 然後,該插件使用dlopenRTLD_GLOBAL加載其他每個共享對象。這在插件之間起作用。但我不確定它 將允許插件返回主界面,但是(但我認爲它應該是 )。和IIRC,當鏈接主要的 其符號可用時,您需要特殊選項。我認爲Linux會將主要的 中的符號看作是否已經裝載了RTLD_LOCAL。 (也許 --export-dynamic?這是一段時間,因爲我不得不這樣做,我 不記得確切。)

+0

我想你幾乎接近真正的解決方案。問題出在RTLD_LOCAL。 OPENGL爲PLUGIN.so.1調用dlopen。 APP與PLUGIN.so鏈接。在scp之後,PLUGIN.so成爲不是軟鏈接到PLUGIN.so.1,而是真正的文件。所以我在進程的地址空間中有兩個文件PLUGIN.so和PLUGIN.so.1。 – fghj

2

它顯然很大程度上取決於庫的功能,但一般情況下應該有一些解決方案。

首先請注意,通常如果一個名稱相同的共享庫被加載多次,它將繼續使用相同的庫。這種主要適用於通過標準加載/鏈接機制加載。如果庫自己調用dlopen,它仍然可以獲得相同的庫,但它取決於標記dlopen。嘗試閱讀dlopen上的文檔,瞭解它是如何工作的以及如何操作它。

您還可以嘗試在鏈接器命令中早先定位PLUGIN,以便它首先被加載,從而可以避免稍後再加載一次。如果你必須動態加載插件,這顯然無濟於事。您還可以檢查LD_PRELOAD是否可以解決鏈接順序。

作爲最後的手段,您可能不得不求助於使用LD_LIBARY_PATH並將真實接口庫放入其中。這隻會將呼叫傳遞給真實的呼叫,但會攔截重複的負載並將其分流到之前的負載。

這只是一個需要考慮的方向。您的實際答案將取決於您的代碼以及其他共享庫的功能。在進入其他選項之前,請首先調查鏈接器加載順序,因爲它是最容易檢查的,然後是dlopen標誌。

相關問題