1. ホーム
  2. c++

[解決済み】共有オブジェクト(.so)、静的ライブラリ(.a)、DLL(.so)の違い?)

2022-03-27 17:23:38

質問

Linuxのライブラリに関する議論に参加したことがあり、いくつか確認したいことがあります。

私の理解では(間違っていたら訂正してください、後で投稿を編集します)、アプリケーションを構築する際にライブラリを使用する方法は2つあると思います。

  1. 静的ライブラリ(.aファイル)。リンク時に、ライブラリ全体のコピーが最終的なアプリケーションに入れられ、ライブラリ内の関数が呼び出し側のアプリケーションで常に利用できるようになります。
  2. 共有オブジェクト(.soファイル)。リンク時、オブジェクトは対応するヘッダー(.h)ファイルを介してそのAPIに対して検証されるだけです。ライブラリは、実行時に必要になるまで、実際には使用されません。

静的ライブラリの明らかな利点は、アプリケーション全体を自己完結させることができることです。一方、動的ライブラリの利点は、ベースアプリケーションを再コンパイルすることなく、".so" ファイルを交換できる(つまり、セキュリティバグにより更新が必要になった場合)ことです。

共有オブジェクトとダイナミックリンクライブラリ(DLL)は同じquot;.so"ファイルですが、区別している人がいると聞いたことがありますが、どうでしょうか?Linuxやその他のPOSIX準拠のOS(MINIX、UNIX、QNXなど)でC/C++を開発する場合、共有オブジェクトとDLLに区別はあるのでしょうか?DLLはアプリケーション内でdlopen()コールを使って最初に開かなければならないのに対して、共有オブジェクトは実行時に使用されるだけだということが(今のところ)一つの重要な違いだと聞いています。

私の理解では、共有アーカイブも静的ライブラリですが、アプリケーションによって直接使用されることはありません。その代わり、他の静的ライブラリは共有アーカイブに対してリンクし、共有アーカイブの関数やリソースの一部(すべてではありません)をビルド中の静的ライブラリに取り込みます。

皆さん、よろしくお願いします。

更新情報


この用語が私に提供された文脈では、Linuxを学ばなければならないWindowsの開発者チームが使った、事実上の誤った用語でした。私はそれらを訂正しようとしましたが、(間違った)言語規範が定着してしまいました。

  1. Shared Objectの略。プログラム起動時に自動的にリンクされ、スタンドアロンファイルとして存在するライブラリ。このライブラリは、コンパイル時にリンクリストに含まれます(例. LDOPTS+=-lmylib という名前のライブラリファイルに対して mylib.so ). ライブラリは、コンパイル時およびアプリケーションの起動時に存在する必要があります。
  2. スタティック・ライブラリ。アプリケーションコードとライブラリコードを含む単一の(より大きな)アプリケーションのビルド時に実際のプログラム自体にマージされるライブラリで、プログラムビルド時にプログラムに自動的にリンクされ、メインプログラムとライブラリ自体の両方を含む最終バイナリは単一のスタンドアロンバイナリファイルとして存在します。ライブラリは、コンパイル時にリンクリストに含まれます(すなわち、: LDOPTS+=-lmylib という名前のライブラリファイルに対して mylib.a ). コンパイル時にライブラリが存在する必要があります。
  3. DLL:基本的には共有オブジェクトと同じですが、コンパイル時にリンクリストに含まれるのではなく、ライブラリは dlopen() / dlsym() コマンドを使用することで、プログラムのコンパイル時にライブラリが存在する必要はありません。 また、アプリケーションの起動時やコンパイル時にライブラリが存在する必要は(必ずしも)ない を実行した瞬間に必要なだけである。 dlopen / dlsym の呼び出しが行われます。
  4. 共有アーカイブ。基本的にはスタティック・ライブラリと同じですが、"export-shared"と".Shared;でコンパイルされたものです。 -fPIC フラグ。このライブラリは、コンパイル時にリンクリストに含まれます (例: LDOPTS+=-lmylibS という名前のライブラリファイルに対して mylibS.a ). この 2 つの違いは、共有オブジェクトまたは DLL が共有アーカイブを自身のコードに静的にリンクし、共有オブジェクト内の関数を DLL 内部で使用するだけでなく、他のプログラムでも使用できるようにしたい場合に、この追加フラグが必要になることです。これは、誰かが静的ライブラリを提供してくれて、それをSOとして再パッケージ化したい場合に便利です。 コンパイル時にライブラリが存在する必要があります。

追加更新

"の区別。 DLL と「" shared library "は、当時私が働いていた会社での(いい加減で不正確な)口語表現(Windows開発者がLinux開発に移行させられ、この言葉が定着した)で、上記の記述に準拠しているだけである。

さらに、末尾の" S 共有アーカイブの場合、ライブラリ名の後に「"」というリテラルを付けるのは、その会社での慣習であり、業界一般ではありません。

解決方法は?

WindowsではDLLと呼ばれ、UNIXシステムでは共有オブジェクトと呼ばれ、ダイナミック・リンク・ライブラリという一般用語が両方をカバーしています(UNIXでは.soをオープンする関数も dlopen() ダイナミックライブラリ」の後)。

確かにアプリケーションの起動時にのみリンクされますが、ヘッダーファイルとの照合という考え方は正しくありません。ヘッダーファイルは、ライブラリを使用するコードをコンパイルするために必要なプロトタイプを定義していますが、リンク時にリンカーはライブラリ自体の内部を見て、必要な関数が実際に存在することを確認します。リンカはリンク時に関数本体をどこかで見つけなければならず、さもなければエラーになります。あなたの指摘するように、ライブラリ自体はプログラムがコンパイルされた後に変更されている可能性がありますから、実行時にも同じことが行われます。ABIが変更されると、古いバージョンに対してコンパイルされた既存のプログラムが壊れてしまうからです。

スタティック・ライブラリは、プロジェクトのコンパイルの一部として自分で構築するのと同じように、コンパイラから直接オブジェクト・ファイルをバンドルしているだけなので、まったく同じ方法でリンカに取り込まれて供給され、まったく同じ方法で未使用のビットが削除されるのです。