7

私が持っているとします:

  • /usr/lib/libsomething.so.1マシン A;
  • /usr/lib/libsomething.so.2マシン B で。

両方のマシンには/usr/lib/libsomething.so、それぞれのライブラリへのシンボリック リンクがあります。

gccwith -lsomething(または)を使用してリンクする/usr/lib/libsomething.soと、シンボリック リンクがたどらlddれ、マシン A では次のようなものが生成されます。

libsomething.so.1 => /usr/lib/libsomething.so.1

これは、マシン B でライブラリを見つけることができないことを意味します。

これらはメジャー バージョン番号の変更であり、互換性がない可能性があることはわかっていますが、そのリスクを冒しても構わないと思っています。リンカに伝えたいのは、 を探すことですlibsomething.so。シンボリックリンクをたどらないので、ldd表示されます

libsomething.so => /usr/lib/libsomething.so.1

Aでしかし

libsomething.so => /usr/lib/libsomething.so.2

B.そして、ローダーはそこにあるバージョンへのシンボリックリンクをたどります。

また、dlopen などで読み込みを遅らせたくありません。コンパイル時に共有オブジェクトにリンクしたい。

これは可能ですか?

4

2 に答える 2

9

もちろん、共有ライブラリの利用可能な任意のバージョンを使用する実行可能ファイルを作成することも可能です。

問題は、実行可能ファイルをバージョン固有のsoname (libsomething.so.1およびlibsomething.so.2) にリンクしたことです。代わりに、バージョン管理されていない soname を使用する必要がありましたlibsomething.so

これを実現するには、ビルド マシンで soname (ELF SONAME) をlibsomething.so(バージョンなしで) 使用してライブラリをコンパイルおよびインストールし、リンカーが実行可能ファイルのビルド中にこの soname を選択できるようにする必要があります。

Shared Libraries HOWTOによると、ライブラリのビルド中に必要なバージョン管理されていないsonameを渡すことができます。

gcc -shared -Wl,-soname,libsomething.so -o libsomething.so.X objectsomething.o

次に、ライブラリをインストールして を実行するとldconfig、次のようになります。

  • マシン A/lib/libsomething.soを指すシンボリック リンク。/lib/libsomething.so.1
  • マシン B/lib/libsomething.soを指すシンボリック リンク。/lib/libsomething.so.2

ローダー ( run ldd) は、それが指す場所に関係なく、バージョン管理されていないシンボリック リンクを選択します。

  • libsomething.so => /lib/libsomething.so (0xNNNNNNNN)マシン A;
  • libsomething.so => /lib/libsomething.so (0xNNNNNNNN)マシン B で。

Linux ダイナミック ローダー ( ld.so) は、実行可能ファイル (ELF ) に書き込まれた soname 値に基づいてライブラリを解決しますNEEDEDSONAME値は、実行可能ファイルのビルド中にライブラリ ファイル (ELF) からコピーされます。実行可能ファイルに記録された soname と一致するシンボリック リンクがターゲット システムに存在する限り、このシンボリック リンクが指すライブラリがロードされます。


設定を実行してコマンドを表示し、仮定を検証してみましょう。

X86_64テストにはFedora 18 を使用しi686、わかりやすくするために出力を に調整しました。

  • libsomething.so.1と の両方をコンパイルしlibsomething.so.2ます。SONAMEunversioned に設定されていることを確認してくださいlibsomething.so:

    readelf -a libsomething.so.1 | grep SONAME
    0xNNNNNNNN (SONAME)             Library soname: [libsomething.so]
    
    readelf -a libsomething.so.2 | grep SONAME
    0xNNNNNNNN (SONAME)             Library soname: [libsomething.so]
    
  • /lib/ディレクトリの下のそれぞれのマシンにライブラリをインストールします。ldconfig -v両方のマシンで実行し、出力を確認します。

    ldconfig -v 2>&1 | grep something
    libsomething.so -> libsomething.so.1 (changed)
    
    ldconfig -v 2>&1 | grep something
    libsomething.so -> libsomething.so.2 (changed)
    
  • 実行可能ファイルをコンパイルし、バージョンのない同じ soname を参照していることを確認しNEEDEDます。

    readelf -a executable | grep NEEDED
    0xNNNNNNNN (NEEDED)             Shared library: [libsomething.so]
    
  • 実行可能ファイルは、現在バージョン管理されていないものに依存してlibsomething.soいます。実行可能ファイルを両方のマシンにコピーし、両方のコピーに対して実行しlddます。

    ldd executable
    libsomething.so => /lib/libsomething.so (0xNNNNNNNN)
    

    実行可能ファイルはバージョンなしの soname でビルドされているため、最後の出力は両方のマシンで同じです。これにより、ローダーはターゲットマシンでバージョン管理されていないシンボリックリンクを取得します。また、マシンによっては、シンボリック リンクがライブラリlibsomething.so.1またはlibsomething.so.2.

于 2013-03-12T19:17:06.993 に答える
2

これは、マシン B でライブラリを見つけることができないことを意味します。

とにかく、それは想定されていません。

soversionsの定義そのものにより、libsomething.so.2は API/ABI が と互換性がないことを示しlibsomething.so.1ます。したがって、ロードするライブラリのプログラムのテーブルに追加libsomething.soするだけでは、実際には間違っています。シンボリックリンクはlibsomething.so、デフォルトでどのバージョンを選択するかについて、ld へのヒントとしてのみ機能します。

ld が実際に開いたファイルが何であれ、プログラムでエンコードするには DTNAME/SONAME フィールドが必要です。それを望まない場合は、libsomething に soname を装備しないでください。しかし、それは簡単に苦痛になる可能性があります...プログラムを実行しようとしたときに使用できないシンボルに遭遇することから始めます。

于 2011-01-14T02:12:21.517 に答える