2010-11-18 96 views
2

我想要dlopen()每個共享庫在特定目錄中。爲了做到這一點,
什麼是最簡單的方式來檢索Linux的庫搜索路徑。還是有更快的方式找到該路徑中的特定目錄?
posix會更好。在共享庫搜索路徑中查找目錄

+0

你的意思是你想'LD_LIBRARY_PATH'的每個目錄中的'dlopen'每個庫? – 2010-11-18 13:46:37

+0

nope,我的意思是在Linux的每個目錄的特定子目錄中替換LD_LIBRARY_PATH中的每個庫。 – 2010-11-19 15:09:08

回答

5

POSIX不支持找到共享庫搜索路徑上的目錄的機制(例如,它沒有授權LD_LIBRARY_PATH),所以任何解決方案本質上都是特定於平臺的。

Linux提出了一些問題,因爲要使用的值可能基於/etc/ld.so.conf的內容以及LD_LIBRARY_PATH環境變量中的任何運行時值;其他系統存在相似的問題。默認位置也因系統而異 - 對於32位Linux機器,/lib/usr/lib是常用的,但在至少一些64位機器上使用/lib64/usr/lib64。但是,其他平臺使用其他位置的64位軟件。例如,Solaris使用/lib/sparcv9/usr/lib/sparcv9,例如(儘管文檔提到/lib/64/usr/lib/64,它們是到sparcv9目錄的符號鏈接)。 Solaris還具有環境變量LD_LIBRARY_PATH_64LD_LIBRARY_PATH_32。 HP-UX和AIX傳統上使用LD_LIBRARY_PATH-SHLIB_PATHLIBPATH,IIRC之外的其他變量 - 儘管我相信AIX現在也使用LD_LIBRARY_PATH。並且,在Solaris上,用於配置共享庫的工具是'crle'(配置運行時鏈接環境),並且/etc/ld.so.conf的模擬爲/var/ld/ld.config/var/ld/64/ld.config。當然,共享庫的擴展名也不盡相同(.so.sl.dylib,.bundle等)。

因此,您的解決方案將是平臺特定的。您需要決定默認位置,要讀取的環境變量,要讀取的配置文件以及相關的文件擴展名。鑑於這些,那麼它主要是一個SMOP - 簡單的事情編程:

  • 對於每個通過任何來源命名的目錄:
    • 打開相關子目錄(opendir()
      • 閱讀各文件名(readdir())依次爲
      • 在相關文件的路徑上使用dlopen()
      • 做任何分析與你有關。
      • 使用dlclose()
    • 使用closedir()

參見在下面的評論的音符......完整的話題是從平臺到平臺間的變化小幅充滿。

+1

一些額外的信息,隨時可以納入回答:LD_PRELOAD還可以指定應該使用的特定庫,而不是在搜索路徑中找到的庫,並且應用程序二進制文件和打開的任何庫可能會有一個RPATH烘焙到它們中指定要查看的其他目錄。你可以通過「objdump -p my_app_or_lib | grep RPATH」來查看Linux上app/lib的RPATH。如果您對RPATH不熟悉,則在鏈接時將「-R/foo」添加到LDFLAGS將導致鏈接器將/ foo插入到二進制文件中,這樣動態鏈接器將在/ foo中查找庫。 – 2010-11-21 01:39:38

+0

很好的答案,謝謝喬納森。雖然這種簡單的事情應該像這樣複雜,但真的很奇怪 – 2012-01-16 15:48:22

1

我不確定有可能做到這一點,並且可攜帶。由於這個問題是關於Linux的,可移植性可能不是最重要的。然後我不明白POSIX約束。你能澄清嗎?

你可能必須要麼實現man 8 ld.so詳細的搜索功能,其中包括除了掃描/etc/ld.so.conf中來LD_LIBRARY_PATH,或使/lib/ld.so你想要做什麼你和解析輸出。對於有未準確,漂亮的命令行可能是:

export LD_PRELOAD=THISLIBRARYSODOESNOTEXIST 
strace -s 4096 /bin/true 2>&1 | sed -n 's/^open("\([^"]*\)\/THISLIBRARYSODOESNOTEXIST".*$/\1\/YOURSUBDIRHERE/gp' 
unset LD_PRELOAD 

然後,您可以枚舉文件與POSIX電話opendir(3)readdir(3)