我正在使用一個共享庫,其中有幾個全局變量, 幾乎用於所有導出的函數 ,因此庫函數不是線程安全的。 我的應用程序創建多個線程,每個線程動態地打開這個 庫,並避免使用並行調用 到導出 功能之間的同步,我的圖書館多次以不同的名稱複製磁盤與 每個線程打開自己的副本。爲了避免這種情況,現在我正在使用dlmopen來代替,但是我正面臨一個問題。未解決的符號只有dlmopen而不是dlopen
當我使用的dlopen在我的應用程序中打開庫,應用程序工作正常
libHandle = dlopen(ip->pathname, (RTLD_LAZY |RTLD_LOCAL|RTLD_DEEPBIND|RTLD_NODELETE));
當我在應用程序而不是使用dlmopen,我得到錯誤:
ip->libHandle = dlmopen(LM_ID_NEWLM, ip->pathname,
(RTLD_LAZY |RTLD_LOCAL|RTLD_DEEPBIND|RTLD_NODELETE));
的dlerror獲得是:
error(libfoo.so.0: undefined symbol: _ZTIN6google8protobuf11MessageLiteE)
做nm顯示符號undefined U _ZTIN6google8protobuf11MessageLiteE
問題1:我想知道如何解決此問題,以便我可以使用dlmopen。
原因是因爲當使用LM_ID_NEWLM時,在libc中沒有任何符號的情況下會創建一個新的空名稱空間。所以這個庫應該是自包含的或者與任何依賴關係重新鏈接。
問題2:我的主應用程序導出libfoo將使用的一些符號。由於在新命名空間中打開libfoo,主應用程序的符號對libfoo不可見,因此無法解析它們。 有沒有什麼辦法告訴鏈接器創建一個新的命名空間NEWLM,通過複製現有的基本命名空間,並使用新創建的命名空間的dlmopen + lmid來打開libfoo,其中所有其他必需的符號已經存在?
問題3:我可以自己mmap libfoo的不同部分,並提供一個指向libc的mmaped部分的指針。意味着需要打開文件並將其從libc中取出並讓其執行符號解析的工作?這樣我就不需要調用dlopen,多個文本部分的問題就可以解決。
感謝您的答覆。將libfoo與libproto以及所有其他所需的庫重新鏈接是可能的。但是我有更大的問題。我的主應用程序導出libfoo將使用的一些符號。由於在新命名空間中打開libfoo,主應用程序的符號對libfoo不可見,因此無法解析它們。有沒有什麼辦法告訴鏈接器創建一個新的命名空間NEWLM,通過複製現有的基本命名空間並使用新創建的命名空間的dlmopen + lmid來打開libfoo,其中所有其他必需的符號已經存在? – ashish
此活動的關鍵是避免由於每個副本實例具有不同的inode號而多次複製同一個庫所導致的文本部分的多個副本。將這與inode相同的情況進行比較。在這種情況下,文本部分將在每個dlopen實例之間共享,而每個都有自己的私人數據副本。不幸的是,dlopen不允許多重打開,因爲libc代碼檢查inode是否已經在當前命名空間中打開。使用dlmopen似乎是合理的(雖然最大限制爲16),但空的命名空間給我的問題。 – ashish
@ user2270067我已經更新了答案。 –