%20%E7%95%AA%E5%8F%B7%E3%81%AF%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB%E6%A9%9F%E8%83%BD%E3%81%97%E3%81%BE%E3%81%99%E3%81%8B%3F.png)
Linux の共有オブジェクトでは「so 番号」が使用されること、つまり、共有オブジェクトの異なるバージョンには異なる拡張子が付けられることを認識しています。たとえば、次のようになります。
example.so.1
example.so.2
2 つの異なるファイルを用意して、システム上に 2 つのバージョンのライブラリが存在できるようにする (Windows の「DLL 地獄」とは対照的) というアイデアだと理解しています。これが実際にどのように機能するかを知りたいのですが。 多くの場合、 は実際example.so
には最新バージョンへのシンボリック リンクです。では、 の古いバージョンに依存するアプリケーションは、それを正しく識別するにはどうすればよいでしょうか。使用しなければならない番号に関する規則はありますか。それとも、これは単なる慣例ですか。ソフトウェア バイナリがシステム間で転送される Windows とは異なり、システムに共有オブジェクトの新しいバージョンがある場合、ソースからコンパイルするときに自動的に古いバージョンにリンクされるのでしょうか。example.so.2
.2
example.so
これは関連していると思われますがldconfig
、どのように関連しているかはわかりません。
答え1
バイナリ自体は、依存する共有ライブラリのバージョンを認識しており、それを具体的に要求します。 を使用してldd
依存関係を表示できます。私の場合は次のようにls
なります。
$ ldd /bin/ls
linux-gate.so.1 => (0xb784e000)
librt.so.1 => /lib/librt.so.1 (0xb782c000)
libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
libc.so.6 => /lib/libc.so.6 (0xb76dc000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
/lib/ld-linux.so.2 (0xb784f000)
libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)
ご覧のとおり、libpthread.so.0
だけではなく、たとえば を指していますlibpthread.so
。
シンボリックリンクの理由はリンカーのためです。直接リンクしたい場合はフラグlibpthread.so
を指定すると、プレフィックスとサフィックスが自動的に追加されます。サフィックスを追加するように指示することはできないので、シンボリックリンクは最新バージョンのライブラリを指して、それを容易にします。gcc
-lpthread
lib
.so
.so.0
答え2
共有ライブラリ内の番号は、Linux でライブラリの API を識別するために使用される規則です。通常、形式は次のとおりです。
libFOO.so.MAJOR.MINOR
お気づきのとおり、通常は libFOO.so から libFOO.so.MAJOR.MINOR へのシンボリック リンクがあります。ldconfig は、このリンクを最新バージョンに更新する役割を担っています。
MAJOR は通常、API が変更されたとき (新しいエントリ ポイントが削除されたとき、またはパラメーターや型が変更されたとき) に増加します。MINOR は通常、バグ修正リリースの場合、または既存の API を壊さずに新しい API が導入された場合に増加します。
より詳しい議論は、こちらでご覧いただけます:共有ライブラリの分析
答え3
共有ライブラリは、次のスキームに従ってバージョン管理する必要があります。
blah.so.X.Y.Z
どこ
- X = 下位互換性のないABIリリース
- Y = 下位互換性のあるABIリリース
- Z = 内部変更のみ - ABI には変更なし
通常、 のように最初の数字だけが表示されますhello.so.1
。これは、他のすべての数字は下位互換性があるため、ライブラリの「バージョン」を識別するために必要なのは最初の数字だけだからです。
ldconfig
システムで利用可能な共有ライブラリとそのライブラリへのパスが存在する場所のテーブルを維持します。これを確認するには、次のコマンドを実行します。
ldconfig -p
Red Hat などのパッケージをビルドする場合、バイナリで呼び出される共有ライブラリが検索され、RPM ビルド時にパッケージの依存関係として追加されます。したがって、パッケージをインストールする場合、インストーラーは をhello.so.1
チェックして、システムに がインストールされているかどうかを検索しますldconfig
。
次のようにすると、パッケージの依存関係を確認できます。
rpm -qpR hello.rpm
このシステムでは (Windows とは異なり)、複数のバージョンをhello.so
システムにインストールし、異なるアプリケーションで同時に使用することができます。
答え4
libNAME.so は、-lNAME で指定されたライブラリを最初に探すときにコンパイラ/リンカーが使用するファイル名です。共有ライブラリ ファイル内には、SONAME と呼ばれるフィールドがあります。このフィールドは、ライブラリ自体がビルド プロセスによって最初に共有オブジェクト (so) にリンクされるときに設定されます。この SONAME は、実際には、リンクされている共有オブジェクトに応じてリンカーが実行可能ファイルに格納するものです。通常、SONAME は libNAME.so.MAJOR の形式であり、ライブラリがリンクされている既存の実行可能ファイルと互換性がなくなったときにいつでも変更されます。また、必要に応じてライブラリの両方のメジャー バージョンをインストールしたままにすることができます (ただし、開発用に libNAME.so としてポイントされるのは 1 つだけです)。また、ライブラリのマイナー バージョン間のアップグレードを容易にするために、libNAME.so.MAJOR は通常、libNAME.so.MAJOR.MINOR のようなファイルへのリンクです。新しいマイナー バージョンをインストールして完了すると、古いマイナー バージョンへのリンクが新しいマイナー バージョンを指すように変更され、すべての新しい実行がアップグレードされたライブラリを使用するように直ちにアップグレードされます。また、Linux、GNU GCC、ld、バージョン スクリプト、ELF バイナリ形式 - どのように動作するのでしょうか?