web-dev-qa-db-ja.com

SO(共有オブジェクト)番号はどのように機能しますか?

Linuxでの共有オブジェクトは「so番号」を使用すること、つまり、共有オブジェクトの異なるバージョンには異なる拡張子が与えられることを知っています。たとえば、次のようになります。

  • example.so.1
  • example.so.2

ライブラリの2つのバージョンがシステムに存在できるように、2つの異なるファイルを使用するという考えを理解しています(Windowsの「DLL Hell」とは対照的です)。これが実際にどのように機能するか知りたいですか?多くの場合、example.soは実際にはexample.so.2へのシンボリックリンクであることがわかります。ここで、.2は最新バージョンです。古いバージョンのexample.soに依存するアプリケーションは、それをどのように正しく識別しますか?どの数字を使用する必要があるかについての規則はありますか?それともこれは単に慣習ですか?システム間でソフトウェアバイナリが転送されるWindowsとは異なり、システムに新しいバージョンの共有オブジェクトがある場合、ソースからコンパイルすると、古いバージョンに自動的にリンクされますか。

これはldconfigに関連しているのではないかと思いますが、方法はわかりません。

127
user119

バイナリ自体は、依存している共有ライブラリのバージョンを認識しており、具体的にそれを要求します。 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サフィックスを追加するように指示することはできないため、シンボリックリンクは最新バージョンのlibをポイントして、それを容易にします。

91
Michael Mrozek

共有ライブラリの番号は、ライブラリのAPIを識別するためにLinuxで使用される規則です。通常、形式は次のとおりです。

libFOO.so.MAJOR.MINOR

そして、通常気付いたように、libFOO.soからlibFOO.so.MAJOR.MINORへのシンボリックリンクがあります。 ldconfigは、このリンクを最新バージョンに更新する責任があります。

MAJORは通常、APIが変更されると増分されます(新しいエントリポイントが削除されるか、パラメーターまたはタイプが変更されます)。マイナーは通常、バグ修正リリースの場合、または既存のAPIを壊すことなく新しいAPIが導入された場合に増分されます。

より広範な議論はここにあります: 共有ライブラリの分析

61
miguel.de.icaza

共有ライブラリは、次のスキームに従ってバージョン管理する必要があります。

blah.so.X.Y.Z

どこ

  • X =下位互換性のないABIリリース
  • Y =下位互換性のあるABIリリース
  • Z =内部変更のみ-ABIへの変更なし

他のすべての桁は下位互換性があるため、通常、最初の桁はhello.so.1のような最初の桁のみが表示されます。これは、最初の桁がライブラリの「バージョン」を識別するために必要な唯一の桁だからです。

ldconfigは、システムで使用可能な共有ライブラリと、そのライブラリへのパスが存在する場所のテーブルを保持します。これを確認するには、次のコマンドを実行します。

ldconfig -p

Red Hatなどのパッケージがビルドされると、バイナリで呼び出されている共有ライブラリが検索され、RPMビルド時にパッケージの依存関係として追加されます。したがって、パッケージをインストールするときに、インストーラーはldconfigをチェックして、hello.so.1がシステムにインストールされているかどうかを調べます。

次のようなことを行うと、パッケージの依存関係を確認できます。

rpm -qpR hello.rpm

このシステム(Windowsとは異なります)では、hello.soの複数のバージョンをシステムにインストールして、さまざまなアプリケーションで同時に使用できます。

25
ascotan

libNAME.soは、-lNAMEで指定されたライブラリーを最初に検索するときにコンパイラー/リンカーが使用するファイル名です。共有ライブラリファイル内には、SONAMEと呼ばれるフィールドがあります。このフィールドは、ライブラリ自体がビルドプロセスによって共有オブジェクト(so)に最初にリンクされるときに設定されます。このSONAMEは、実際には、リンクされている共有オブジェクトに応じて、リンカーが実行可能ファイルに格納するものです。通常、SONAMEはlibNAME.so.MAJORの形式であり、ライブラリがそれにリンクされている既存の実行可能ファイルと互換性がなくなり、ライブラリの両方のメジャーバージョンを必要に応じてインストールしておくことができます(ただし、開発用に指定されるのは1つだけです)。 libNAME.soとして)また、ライブラリのマイナーバージョン間のアップグレードを簡単にサポートするために、libNAME.so.MAJORは通常、libNAME.so.MAJOR.MINORのようなファイルへのリンクです。新しいマイナーバージョンをインストールでき、完了すると、古いマイナーバージョンへのリンクがバンプされ、新しいマイナーバージョンがすべての新しい実行をすぐにアップグレードして、アップグレードされたライブラリを使用します。また、私の回答もご覧ください Linux、GNU GCC、ld、versionスクリプトとELFバイナリ形式-どのように機能しますか?

20
penguin359