Linuxの共有ライブラリに関する世界観です。
ライブラリとは、それ自体が起動して実行することのできるプログラムではなく、ほかのプログラムから呼び出されることで、さまざまな便利な機能を提供してくれるプログラムのこと。
UNIXでは、基本的なライブラリとしてlibcやxlibがあるが、ほかにも、たとえばGTKのライブラリなどを使うことで、GTKプログラミングが自分でできるようになったりする。
しかしながら、ライブラリを使ったプログラムは、それだけを導入しても、ライブラリの共有オブジェクトがシステムに存在しなければ動作しない。GTKのライブラリが一通り導入されていなければ、当たり前だがGTKアプリケーションは動作しない。このため、依存パッケージの管理のためにパッケージ管理システムを用いる。
また、もし実行できたとしても、プログラムをなんらかの理由でソースコードからコンパイル・ビルドするためには、ライブラリのAPI(関数やグローバル変数のプロトタイプ宣言など)が記述されたヘッダファイルが必要となる。このためには、ヘッダファイルが含まれている-develパッケージを導入することが必要となる。また、gccなどの開発ツール(ツールチェイン)が一通り導入されている必要もある(Red Hatなどではデフォルトでgccすら含まれていないことがある)。
UNIXシステム管理(コンパイラ)も参照のこと。
基本的に、拡張子*.aで終わるライブラリは、静的リンク(スタティックリンク)を行うライブラリ。これに対して、拡張子*.soで終わるライブラリは、動的リンク(ダイナミックリンク)を行うライブラリ。
スタティックリンクでは、プログラムのコンパイル時に静的にプログラムにライブラリが結合される。これに対してダイナミックリンクでは、プログラムのコンパイル時には結合されず、プログラムとライブラリのオブジェクト(共有ライブラリ、shared object)が別々に作成され、実行時にLinuxのリンクローダ(ld-linux.so.2)が動的にリンクを行ってプログラムを実行する。
昔のUNIXシステムには、スタティックリンクしか存在しなかった。ダイナミックリンクが導入されてからは、さまざまなメリットから、ダイナミックリンクを使うことが一般的で、Linuxでもダイナミックリンクを使うことが標準的となっている。
スタティックリンクに比べた時のダイナミックリンクのメリットとして、ファイルサイズの削減とメモリイメージの共有が言える。ライブラリを物理的に結合しないため、プログラムのファイルサイズの削減となる。また、メモリ領域において単一のライブラリイメージをすべてのプログラムで共有するため、メモリ領域の大幅な削減となる。ダイナミックリンクのオーバーヘッドがたとえあったとしても、ダイナミックリンクを用いることができる環境では、ダイナミックリンクの方がシステムのパフォーマンスがよくなることが多い。
また、ここでABIという話をする。ABIとはアプリケーションのバイナリのインターフェースであり、ソースコードレベルのインターフェースであるAPIと違って、ABIはバイナリレベルでのインターフェースである。もし、ABIがきちんと保たれている環境であったとしたら、共有ライブラリの方がシステムのバージョンが変わった時の変更がしやすい。共有ライブラリだけを更新すればよく、アプリケーションレベルでの再リンクが必要ないからである。このため、OSのバージョン更新などでも、仕様が大幅に変わっていない場合、ダイナミックリンクの方が対応しやすい。
共有ライブラリのデメリットとしては、依存関係を把握しづらいことが言える。プログラムが依存している共有ライブラリがシステムに存在しなければ、そのプログラムは動作しない。また、libcなどの重要な共有ライブラリのバージョンを上げる時に、もし仕様が変わっていてABIが保たれていなければ、システムの多くの部分に障害が発生する危険性もある(スタティックリンクだからといって、再リンクと同時に動かなくなる可能性はある)。
より詳しく書かれている書籍としては以下が参考になります。
コマンド | 説明 |
---|---|
ldd | プログラムの実行ファイル(バイナリ)の依存する共有ライブラリを表示する。 |
ldconfig | 共有ライブラリのためのリンクを作成し、キャッシュを更新する。 |
2024.10.06編集
lddコマンドは、引数に指定した実行ファイルが利用している共有ライブラリを表示する。
$ ldd /bin/ls (lsの依存関係にある共有ライブラリが表示される)
基本的に、通常は/libや/lib64に共有ライブラリが置かれる。これは/usr/libや/usr/lib64などのシンボリックリンクになっていることもある。
だが、これよりも優先度が上となるのが、システムの環境変数LD_LIBRARY_PATHやLD_LIBRARY_PATH_64、あるいは設定ファイル/etc/ld.so.confに記述された共有ライブラリの置かれるディレクトリパス。
/etc/ld.so.confの設定は、ldconfigコマンドを実行することによってシステムに反映させることができる。
具体的には、/etc/ld.so.conf.d/以下にhoge.confを作ってこの中に共有ライブラリの置かれるディレクトリパスを記述し、ldconfigコマンドを実行してキャッシュ(/etc/ld.so.cache)を更新する。
Linuxファイルシステム階層も参照のこと。
基本的に、
$ gcc -shared -fPIC -o libhoge.so hoge.c
とする。ここで「-shared」が共有ライブラリの指定の意味となる。
Linuxの共有ライブラリを作るためには、gccに「-fpic」または「-fPIC」を指定し(x86ではどちらも同じ)、PIC (Position Independent Code)としてコンパイルをかける必要がある。(PICでなくてもコンパイルはできるが、PICのほうがいろいろとよい。)
詳しくは以下を参照のこと。
2023.01.21編集
以下のページ・書籍が参考になります。
Linuxヘッダファイルを参照のこと。
GNUツールチェインを参照のこと。
libcやLinux API(stdio)を参照のこと。
Linuxカーネル(ソースコード・カーネルモジュール)を参照のこと。