共有ライブラリ
共有ライブラリは出題数こそ多くありませんが、登場するファイルとコマンドが少ないぶん取りこぼしが許されない範囲です。問われるのは、実行ファイルの依存を調べるコマンド、探索パスを書くファイル、キャッシュを作り直すコマンド、一時的にパスを足す環境変数の4点です。
場所が分からなくなると一斉に止まります
ライブラリの機能を実行ファイルの中に埋め込むのが静的リンク、実行時に外部のファイルを読み込むのが動的リンクです。
| 観点 | 静的リンク | 動的リンク |
|---|---|---|
| 実行ファイルの大きさ | 大きい | 小さい |
| ライブラリの更新 | 再リンクが必要 | ライブラリを差し替えるだけ |
| メモリ | プロセスごとに重複 | 複数プロセスで共有できる |
| 拡張子の慣習 | .a | .so |
| 起動時の依存 | 無し | ライブラリが見つからないと起動しない |
Linux の一般的なコマンドはほぼ動的リンクです。だからこそライブラリの場所が分からなくなると、コマンドが一斉に動かなくなる事故が起きます。
ファイル名にも段階があります。実体が libc.so.6.0.0 のようなフルバージョン名、その一段上が libc.so.6 という soname、開発用のリンク名として libc.so が置かれます。soname の数字はメジャーバージョンで、この数字が変わると互換性が無いという約束です。実行ファイルは soname を覚えているので、libc.so.6 の中でマイナーバージョンが上がるぶんには何もせず追従できます。
ldd で not found を探す
実行ファイルが必要とする共有ライブラリを、実際に解決した結果とともに表示します。
ターミナル
ldd /bin/catlibc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7d00000) のような行が並びます。矢印の左が求められている soname、右が実際に見つかった場所です。右が not found なら、そのライブラリが見つかっておらず、コマンドが起動できない原因になります。linux-gate.so.1 や ld-linux.so.2 のように、ファイルとして存在しない仮想的な行が混ざることもあります。
探索パスを足すのは2手
動的リンカが探す順番は、環境変数 LD_LIBRARY_PATH、/etc/ld.so.cache に登録された場所、/lib や /usr/lib などの既定のディレクトリ、の順です。
| 対象 | 役割 |
|---|---|
/etc/ld.so.conf | 探索対象の設定。多くは include /etc/ld.so.conf.d/*.conf の1行 |
/etc/ld.so.conf.d/*.conf | 1行1ディレクトリで追加パスを書く分割設定 |
ldconfig | 設定を読んでキャッシュを作り直す |
/etc/ld.so.cache | 生成されたバイナリのキャッシュ。直接編集しない |
ldconfig -p | 現在のキャッシュに載っているライブラリを一覧する |
独自の場所にライブラリを置いたときの手順は、設定ファイルにディレクトリを1行足して ldconfig を実行するという2手です。設定を書いただけでは反映されません。
LD_LIBRARY_PATH にコロン区切りでディレクトリを並べると、キャッシュより先にそこが探索されます。設定ファイルを触らずに一時的な検証をしたいときに使います。
ターミナル
export LD_LIBRARY_PATH=/opt/myapp/libただし常用は勧められません。シェルを閉じれば消えますし、意図しないライブラリを掴んで別のプログラムが壊れる原因になります。恒久的な設定は /etc/ld.so.conf.d/ に書くのが正しいやり方です。
よくある引っかけ
ldconfig は設定を書いた後に必ず実行します。書いただけでは /etc/ld.so.cache は古いままです。そのキャッシュはバイナリなので手で編集せず、ldconfig に作らせます。
ldconfig -p はキャッシュの一覧表示であって、作成ではありません。作成はオプション無しの ldconfig です。
LD_LIBRARY_PATH はキャッシュより優先されます。優先順位を逆に覚えていると誤答します。そして ldd は依存の一覧を出すだけで、ライブラリを入れる道具ではありません。