質問
私がする時 ls -l
の /usr/lib
たくさんのLibsが見えます "sameName.so.*.*"
拡大。
- これらの拡張機能の重要性は何ですか?
- なぜソフトリンクが作成されるのですか?彼らの使用は何ですか?
1つの例は、理解に大いに役立ちます。
解決
これは、共有オブジェクトファイルのバージョンに使用されるトリックです。それは、怠zyなリンクのために生じた恐ろしいdll地獄を避ける方法です。
怠lingリンク(または拘束力のある拘束力)の利点は、実際にそれらの実行可能ファイルをリンクすることなく、実行可能ファイルのコンポーネントを変更できることです。これにより、新しい実行可能ファイルなどを発送することなく、サードパーティのコンポーネントでバグ修正が可能になります。
欠点は利点とまったく同じです。実行可能ファイルは、基礎となるライブラリについて行った仮定が変更されており、これがあらゆる種類の問題を引き起こす可能性が高いことを発見できます。
共有オブジェクトのバージョン化は、これを回避する1つの方法です。もう1つはそうです いいえ オブジェクトをまったく共有しますが、それは私がここには入らない長所と短所も持っています。
例として、バージョン1があるとしましょう xyz.so
. 。ファイルとそのファイルへのシンボリックリンクがあります。
pax> ls -al xyz*
-rw-r--r-- 1 pax paxgroup 12345 Nov 18 2009 xyz.so.1
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so -> xyz.so.1
これで、実行可能ファイルを作成するとき exe1
, 、それをリンクします xyz.so
, 、それはシンボリックリンクに従い、それが保存するようにします xyz.so.1
実行可能ファイルでは、実行時にロードする必要があります。
そうすれば、共有ライブラリをアップグレードするとき:
pax> ls -al xyz*
-rw-r--r-- 1 pax paxgroup 12345 Nov 18 2009 xyz.so.1
-rw-r--r-- 1 pax paxgroup 67890 Nov 18 2009 xyz.so.2
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so -> xyz.so.2
元の実行可能ファイル exe1
意思 まだ 共有オブジェクトのバージョン1をロードします。
ただし、現在作成している実行可能ファイル( exe2
)共有オブジェクトのバージョン2にリンクされます。
実際の実装の詳細は多少異なる場合があります(私は以前のUnixesに基づいて答えを下しており、Linuxは単に象徴的なリンクに従うよりも少しインテリジェントにバージョンを実行するように見えます)。 IBM DeveloperWorksには、それがどのように行われているかについての素晴らしい記事があります ここ.
共有オブジェクトを作成すると、本名と soname
. 。これらは、共有オブジェクトをインストールするために使用されます(オブジェクトとリンクの両方を作成します)。
だからあなたは状況に終わることができます:
pax> ls -al xyz*
-rw-r--r-- 1 pax paxgroup 12345 Nov 18 2009 xyz.so.1.5
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so.1 -> xyz.so.1.5
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so -> xyz.so.1
と xyz.so.1.5
所有 SONAME
の xyz.so.1
.
リンカーがリンクするとき xyz.so
, 、それはずっとリンクに従います xyz.so.1.5
そしてそれを使用します SONAME
の xyz.so.1
実行可能ファイルに保存します。それから、あなたがいつ 走る 実行可能、ロードしようとします xyz.so.1
特定を指します xyz.so.1.N
(必ずしもバージョン1.5ではありません)。
インストールできます xyz.so.1.6
更新します xyz.so.1
代わりにそれを指すためにリンクし、すでにリンクされた実行可能ファイルは代わりにそれを使用します。
このマルチレイヤー方法の1つの利点は、同じ名前の複数の潜在的に互換性のないライブラリを持つことができることです(xyz.so.1.*
, xyz.so.2.*
)しかし、各メジャーバージョン内で、それらを自由にアップグレードできます それらは互換性があるはずだからです.
新しい実行可能ファイルをリンクするとき:
- リンクするもの
xyz.so
最新のメジャーバージョンの最新バージョンを取得します。 - 他の人がリンクしています
xyz.so.1
特定のメジャーバージョンの最新のマイナーバージョンを取得します。 - さらに他の人がリンクしています
xyz.so.1.2
特定のメジャーバージョンの特定のマイナーバージョンを取得します。
他のヒント
それは 共有ライブラリのバージョン化スキーム. 。すべてのライブラリには3つの名前が必要です。
- 本名: 実際のライブラリ名、
libfoo.so.1.2.3
- 「ソナメ」: 実行可能ファイルに記録された名前、およびダイナミックリンカーという名前が探しています。
libfoo.so.1.2
. 。この名前は、実際にはライブラリバイナリ自体内で記述されており、リンク時に実行可能ファイルに記録されます。通常、ライブラリの本名(通常は最新バージョン)のシンリンクです。 - リンカー名: プログラムを構築するときにリンカーに与える名前。通常、最新のソナメにリンクします。
例
あなたが持っていると言ってください libfoo
インストールされているバージョン1: libfoo.so
-> libfoo.so.1.0
-> libfoo.so.1.0.0
. 。あなたはあなたのプログラムを構築します bar
と -lfoo
. 。今ではリンクしています libfoo
ロードします libfoo.so.1.0
Sonameによる実行時。次に、パッチをかけたがバイナリ互換性にアップグレードします libfoo.so.1.0.1
実際のバイナリを置き換えることにより。 bar
まだリンクしています libfoo.so.1.0
再構築する必要はありません。
今、あなたが新しいプログラムを構築したいと想像してください baz
これは、libfoo v1.1の互換性のない変化を利用します。新しいバージョンをインストールすると、システムに2つのバージョンが並行してインストールされています。
libfoo.so.1.0
->libfoo.so.1.0.1
libfoo.so
->libfoo.so.1.1
->libfoo.so.1.1.0
ノートリンカー名は最新バージョンに更新されました(これは、インストールしたヘッダーに対応するバージョンです /usr/include
).
あなたは構築します baz
, 、そしてそれはにリンクします libfoo.so
そしてロード libfoo.so.1.1
実行時に。しないこと bar
まだ反対しています libfoo.so.1.0
更新する必要はありません。