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


123

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

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

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

これは関連していると思われますldconfigが、どうすればよいかわかりません。

回答:


87

バイナリ自体は、依存する共有ライブラリのバージョンを認識し、具体的に要求します。を使用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を指し、それを容易にします


等号「= ls」は存在しないはずです。「ldd ls」を使用してください
bmacnaughton

1
@bmacnaughton ldd実行可能ファイルへの完全なパスが必要なため、おそらくエラーが発生します。=lszshでそれを行いますが、誰もがそのシェルを使用しているわけではないので変更しました
Michael Mrozek

面白い。Ubuntuでbashを実行していますが、完全なパスがなくても機能するようです。説明をありがとう-私はzshを使用しません。
bmacnaughton

60

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

libFOO.so.MAJOR.MINOR

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

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

より詳細な議論はここで見つけることができます:共有ライブラリの分析


こんにちはミゲル、そのおかげで、残念ながら上記をうまく補完するため、2つの答えを受け入れることはできません。私からの+1、素晴らしいリンクも、ありがとう!

4
それはほぼ正しいですが、実際はlibFOO.so.MAJOR.MINOR(最後ではありません)
-JonnyJD

6
この答えはとても間違っています。まず、表示される数値はAPIとは関係ありません。これらは純粋にABIです。第二に、ここでの慣習は、あなたが提案するようにセマンティックなバージョン管理ではありません。むしろ、ld.soが比較できる単一のライブラリバージョン番号にマッピングするという優れた特性を持つlibtoolの規則です(詳細については、gnu.org / software / libtool / manual / html_node /…を参照)
NewbiZ

23

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

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インストールし、同時に異なるアプリケーションで使用できます。


これが最良の答えだと思います。
ケミン周

1
共有ライブラリは、次のスキームに従ってバージョン管理する必要があります(…) –このステートメントのリファレンスを提供してください。
ピョートルドブロゴスト

19

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.