Linux の 101 試験対策: 共有ライブラリーの管理

プログラムに必要なライブラリーを発見し、ロードする

どの共有ライブラリーに Linux の実行可能プログラムが依存しているのかを判断する方法、またそれらのライブラリーをロードする方法を学びましょう。このチュートリアルの内容は、Linux システム管理者認定用の LPI 101 試験に備えて勉強するために利用することも、楽しんで学習するために利用することもできます。

Ian Shields, Linux Author, Freelance

Ian ShieldsIan Shields は、Linux のフリー・ライターです。ノースカロライナ州 Research Triangle Park にある IBM を退職した彼が、オーストラリアのキャンベラにある IBM にシステム・エンジニアとして入社したのが 1973年であり、それ以降、カナダのモントリオールやノースカロナイナ州 Research Triangle Park でシステム・エンジニアリングとソフトウェア開発の両方に携わってきました。1990年代後半からは、Linux を使用して Linux 上で開発を行うとともに、Linux に関する執筆も行ってきました。彼は、オーストラリア国立大学で純粋数学および哲学の学士号を取得し、ノースカロライナ州立大学でコンピューター・サイエンスの修士号と博士号を取得しています。普段はオリエンテーリングを楽しんでおり、旅行に行くのも好きです。



2015年 12月 17日 (初版 2010年 3月 10日)

より詳しく学び、さらなる開発を行い、より多くの人とつながる

新たに登場した developerWorks Premium メンバーシップ・プログラムでは、メンバーになると、強力な開発ツールのほか、Safari Books Online を通じて提供される最もホットな 500 タイトルの技術書 (Java 開発者向けのものが大量にあります) を含む各種のリソースをすべて自由に利用できるようになります。さらに、主要な開発者向けイベントの登録料の大幅な割引や、最新の O'Reilly カンファレンスの全容を閲覧できる再生動画など、その他にもさまざまな特典が提供されます。

概要

このチュートリアルでは、Linux プログラムで必要な共有ライブラリーを発見、ロードする方法について学びます。この記事で説明する内容は以下のとおりです。

  • プログラムに必要なライブラリーを判断する方法
  • システムが共有ライブラリーを発見する方法
  • 共有ライブラリーをロードする方法

共有ライブラリー

通常、プログラムを作成するときには、誰か他の人が何らかのルーチンや特殊な機能を実行するために既に作成済みのコードのさまざまな部分を利用します。こうしたコードの部分は、共有ライブラリーに保管されます。共有ライブラリーを使用するには、プログラムをビルドする際、またはプログラムを実行する際のいずれかで、共有ライブラリーを自分のコードにリンクします。

この連載について

この連載は Linux システム管理タスクの学習に役立つだけでなく、Linux Professional Institute の LPIC-1: Linux Server Professional Certification 試験に備えるための教材にもなります。

連載の各チュートリアルに関する説明とリンクについては、developerWorks の「Linux の 101 試験対策: LPIC-1 のロードマップ」を参照してください。現在進行中のこのロードマップは、2015年 4月 15日に更新された LPIC-1 試験の項目のバージョン 4.0 を反映しています。完成したチュートリアルは、その都度ロードマップに追加されていきます。

このチュートリアルは、Linux Server Professional (LPIC-1) 101 試験の主題 102 の 102.3 の試験対策に役立ちます。この試験項目の重要度は 1 です。

前提条件

この連載のチュートリアルを最大限に活用するには、Linux の基礎知識と、記事に記載されたコマンドを演習できる実際の Linux システムが必要です。プログラムのバージョンによって出力のフォーマットに違いが出てくる場合もあるため、コマンドの実行結果は必ずしもここに記載するリストや図とまったく同じであるとは限りません。特に、このチュートリアルで紹介する例の多くは 64 ビット・システムによる結果を示しています。ここでは 32 ビット・システムと 64 ビット・システムとで大きく異なる点を示すために、32 ビット・システムの例もいくつか含めてあります。


静的リンクと動的リンク

Linux システムには次の 2 つのタイプの実行可能プログラムがあります。

  • 静的にリンクされた実行可能プログラム: 静的にリンクされた実行可能プログラムには、それらのプログラムが実行する必要のあるライブラリー関数がすべて含まれており、すべてのライブラリー関数は、その実行可能プログラムにリンクされています。これらのライブラリー関数は完全なプログラムであり、実行のために外部のライブラリーに依存することはありません。静的にリンクされたプログラムの利点の 1 つは、何も前提となる条件をインストールしなくても動作することです。
  • 動的にリンクされた実行可能プログラム: 動的にリンクされた実行可能プログラムは (静的にリンクされた実行可能プログラムよりも) はるかに小さなプログラムであり、実行には外部の共有ライブラリーの関数が必要であるという点で不完全です。小さなプログラムであることに加え、動的にリンクすることによって、必要なライブラリーを実際にパッケージに含めることなくライブラリーとして指定することができます。また動的なリンクを使用することによって、実行中の多数のプログラムがライブラリーの 1 つのコピーを共有することができ、同じコードのコピーが多数あるためにメモリーが占有されてしまうことがありません。こうした理由から、現在はほとんどのプログラムが動的リンクを使用しています。

多くの Linux システムでの興味深い例として、ファイル間のリンク (ハード・リンクあるいはソフト (またはシンボリック) リンク) を作成する ln コマンド (/bin/ln) があります。このコマンドは共有ライブラリーを使用します。共有ライブラリーには、汎用のライブラリー名と特定レベルのライブラリーとの間にシンボリック・リンクがある場合がよくあります。そのため、何らかの理由でリンクが存在しない場合、あるいはリンクが切れている場合には、ln コマンドそのものが動作不能となり、その結果他のコマンドも使えない、という問題が発生します。この問題の発生を防ぐために、一部の Linux システムには、静的リンク・バージョンの ln プログラムが sln プログラム (/sbin/sln) として含まれています。リスト 1 は、動的リンクの ln と静的リンクの sln とでサイズに大きな違いがあることを示しています。この例は Fedora 22 の 64 ビット・システムから引用したものです。

リスト 1. sln と ln のサイズの違い
[ian@atticf20 ~]$ # Fedora 22 64-bit
[ian@atticf20 ~]$ ls -l /sbin/sln /bin/ln
-rwxr-xr-x. 1 root root  58656 May 14 04:56 /bin/ln
-rwxr-xr-x. 1 root root 762872 Feb 23 10:36 /sbin/sln

どのライブラリーが必要なのか?

このトピックは、現在の LPI 試験の出題範囲には含まれていませんが、現在の Linux システムの多くが 32 ビットと 64 ビット両方の実行可能プログラムをサポートするハードウェア上で実行されることを知っておく必要があります。そのため、多くのライブラリーは 32 ビットのバージョンと 64 ビットのバージョンにコンパイルされます。64 ビットのバージョンは通常、ファイルシステムの /lib64 ツリーの下に保存され、32 ビットのバージョンは従来の /lib ツリーの下に保存されます。典型的な 64 ビット Linux システムには通常、/lib/libc-2.11.1.so と /lib64/libc-2.11.1.so の両方があります。この 2 つのライブラリーがあるため、64 ビット Linux システム上で 32 ビットの C プログラムと 64 ビットの C プログラムの両方を実行させることができます。

ldd コマンド

静的にリンクされたプログラムのサイズは大きいことを認識しておくにしても、あるプログラムが静的にリンクされているかどうかを、どのようにして判断するのでしょう?また、プログラムが動的にリンクされている場合、そのプログラムに必要なライブラリーをどのようにして知るのでしょう? ldd コマンドは、この両方の質問に答えることができます。Debian や Ubuntu などのシステムを実行している場合には、おそらく sln 実行可能プログラムはないはずです。そのため、/sbin/ldconfig 実行可能プログラムがないかどうかも調べる必要があります。リスト 2 は、ln および sln 実行可能プログラム、そして ldconfig 実行可能プログラムに対して ldd コマンドを実行した場合の出力を示しています。この例は Fedora 22 の 64 ビット・システム (atticf20) から引用したものです。比較のために、Ubuntu 14 の 32 ビット・システム (attic-u14) の /bin/ln に対して ldd コマンドを実行した場合の出力を示してあります。

リスト 2. sln と ln に ldd を実行した場合の出力
[ian@atticf20 ~]$ # Fedora 22 64-bit
[ian@atticf20 ~]$ ldd /sbin/sln /sbin/ldconfig /bin/ln
/sbin/sln:
	not a dynamic executable
/sbin/ldconfig:
	not a dynamic executable
/bin/ln:
	linux-vdso.so.1 (0x00007ffedd31e000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f2d3bd5d000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f2d3c11d000)

ian@attic-u14:~/data/lpic-1$ # Ubuntu 14 32-bit
ian@attic-u14:~/data/lpic-1$ ldd /bin/ln
	linux-gate.so.1 =>  (0xb779d000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75d7000)
	/lib/ld-linux.so.2 (0xb77a0000)

ldd は実際には動的リンクを調べるためのものであるため、ldd を実行すると、sln と ldconfig に関してはどちらも「not a dynamic executable (動的な実行ファイルではない)」という表示がされ、このことから sln も ldconfig も静的にリンクされていることがわかります。また ldd は ln コマンドに必要な 3 つの共有ライブラリーの名前 (linux-vdso.so.1、libc.so.6、/lib64/ld-linux-x86-64.so.2) を表示します。ここで、.so は、これらが共有オブジェクトまたは動的ライブラリーであることを示すことに注意してください。またこの出力から、3 つの異なる種類の情報があることがわかります。

linux-vdso.so.1
これは Linux Virtual Dynamic Shared Object です。これについてはこのすぐ後に説明します。また Ubuntu 14 の場合のように、linux-gate.so.1 と表示される場合もあります。
libc.so.6
/lib64/libc.so.6 または /lib/i386-linux-gnu/libc.so.6 へのポインターが含まれています。古い 32 ビット・システムでは、ポインターが /lib/libc.so.6 を指している場合もあります。
/lib64/ld-linux-x86-64.so.2
別のライブラリーへの絶対パスです。

リスト 3 では、ls -l コマンドを使うことで、上記 2 番目と 3 番目のライブラリーがそれぞれ特定のバージョンのライブラリーへのシンボリック・リンクであることを示しています。この例は Fedora 22 の 64 ビット・システムから引用したものです。このようにすることで、ライブラリーを使用しているすべての実行可能ファイルを再度リンクしなくても、ライブラリーの更新をインストールできるようになっています。

リスト 3. ライブラリーへのシンボリック・リンク
[ian@atticf20 ~]$ # Fedora 22 64-bit
[ian@atticf20 ~]$ ls -l /lib64/libc.so.6 /lib64/ld-linux-x86-64.so.2
lrwxrwxrwx. 1 root root 10 Feb 23 10:33 /lib64/ld-linux-x86-64.so.2 -> ld-2.21.so
lrwxrwxrwx. 1 root root 12 Feb 23 10:33 /lib64/libc.so.6 -> libc-2.21.so

Linux Virtual Dynamic Shared Objects

x86 プロセッサーの初期の頃、ユーザー・プログラムからスーパーバイザー・サービスへの通信はソフトウェア割り込みによって行われていました。プロセッサーが高速化されるにつれ、これは深刻なボトルネックになりました。Intel では、Pentium II プロセッサーのときから、割り込みの代わりに SYSENTER 命令と SYSEXIT 命令を使ってシステム・コールを高速化する Fast System Call 機能を導入しました。

linux-vdso.so.1 として見えるライブラリーは、仮想ライブラリー、つまり各プログラムのアドレス空間のみに配置された Virtual Dynamic Shared Object です。このライブラリーを linux-gate.so.1 と呼んでいるシステムもあります。この仮想ライブラリーはユーザー・プログラムがシステム関数にアクセスするために必要なロジックを提供します。アクセスの手段としては、割り込みであれ、あるいは最新のプロセッサーでの Fast System Call であれ、その特定のプロセッサーで利用可能な最も高速な手段が使われます。


動的なロード

上記の説明から、/lib/ld-linux.so.2 とその 64 ビット版である /lib64/ld-linux-x86-64.so.2 (どちらも共有ライブラリーのように見えます) が、実際にはそれ自体が実行可能プログラムであると知って驚いた人がいるかもしれません。これらのライブラリーは動的なロードを行うコードであり、実行可能プログラムのヘッダー情報を読み取ります (ヘッダー情報は Executable and Linking Format (ELF) フォーマットです)。このヘッダー情報から、どんなライブラリーが必要か、どのライブラリーをロードする必要があるかを判断します。次に、動的なリンクを実行することで、ロードされたライブラリーと実行可能プログラムに含まれるアドレス・ポインターをすべて修正し、プログラムが実行されるようにします。

ld-linux.so の man ページには、初期の a.out バイナリー・フォーマットに対して同様の操作を行うものであった ld.so も説明されています。リスト 4 は、リスト 2ldd コマンドを使って表示したものと同じ情報を ln コマンドで表示するために、ld-linux.so とその 64 ビット版の --list オプションを使う方法を示しています。

リスト 4. ld-linux.so を使って必要なライブラリーを表示する
[ian@atticf20 ~]$ # Fedora 22 64-bit
[ian@atticf20 ~]$ /lib64/ld-linux-x86-64.so.2 --list /bin/ln
	linux-vdso.so.1 (0x00007ffe725f6000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f2179b5d000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f2179f1d000)

ian@attic-u14:~$ # Ubuntu 14 32-bit
ian@attic-u14:~$ /lib/ld-linux.so.2 --list /bin/ln
	linux-gate.so.1 =>  (0xb77bc000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75f6000)
	/lib/ld-linux.so.2 (0xb77bf000)

2 つのリストの間で 16 進のアドレスが異なる可能性があることに注意してください。ldd を 2 度実行した場合にも 16 進のアドレスが異なる可能性があります。


動的ライブラリーの構成

では動的ローダーは、実行可能ファイルの検索場所をどのようにして知るのでしょう。Linux ではよくあることですが、/etc には構成ファイルがあります。実際には /etc/ld.so.conf と /etc/ld.so.cache という 2 つのファイルがあります。リスト 5 は、64 ビット Fedora 22 システムの /etc/ld.so.conf の内容を示しています。/etc/ld.so.conf では、ld.so.conf.d サブディレクトリーの .conf ファイルがすべて含まれるように指定していることに注意してください。古いシステムでは、すべてのエントリーが /etc/ld/so/conf に含まれており、/etc/ld.so.conf.d ディレクトリーのエントリーが含まれていないかもしれません。/etc/ld.so.conf ディレクトリーまたは /etc/ld.so.conf.d ディレクトリーの実際の内容はシステムによって異なる可能性があります。

リスト 5. /etc/ld.so.conf の内容
[ian@atticf20 ~]$ # Fedora 22 64-bit
[ian@atticf20 ~]$ cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
[ian@atticf20 ~]$ ls /etc/ld.so.conf.d/*.conf
/etc/ld.so.conf.d/atlas-x86_64.conf
/etc/ld.so.conf.d/bind99-x86_64.conf
/etc/ld.so.conf.d/kernel-4.0.4-301.fc22.x86_64.conf
/etc/ld.so.conf.d/kernel-4.0.4-303.fc22.x86_64.conf
/etc/ld.so.conf.d/kernel-4.0.6-300.fc22.x86_64.conf
/etc/ld.so.conf.d/libiscsi-x86_64.conf
/etc/ld.so.conf.d/llvm-x86_64.conf
/etc/ld.so.conf.d/mariadb-x86_64.conf

プログラムのロードは高速でなければなりません。そのため、ldconfig コマンドを使用することで、ld.so.conf ファイル、ld.so.conf.d ディレクトリーに含まれるすべてのファイル、信頼できるディレクトリーと /lib、/usr/lib に含まれるライブラリー、そしてその他コマンドラインに入力されたものすべてを処理します。ldconfig コマンドによって必要なリンクが作成され、また最近使用された共有ライブラリーに対するキャッシュが /etc/ld.so.cache に作成されます。動的ローダーは ld.so.cache にキャッシュされた情報を使用して、動的なロードとリンクが必要なファイルを検索します。ld.so.conf を変更した場合には (あるいは ld.so.conf.d に新たにファイルを追加した場合には)、ldconfig コマンドを (root として) 実行して ld.so.cache ファイルを作り直す必要があります。

通常、ld.so.cache を作り直す場合には、パラメーターを付けずに ldconfig コマンドを使います。他のいくつかのパラメーターを指定すると、このデフォルト動作を変更することができます。いつものように、詳細については man ldconfig で調べてみてください。リスト 6-p パラメーターを使って ld.so.cache の内容を表示する方法を示しています。

リスト 6. ldconfig を使って ld.so.cache を表示する
[ian@atticf20 ~]$ # Fedora 22 64-bit
[ian@atticf20 ~]$ /sbin/ldconfig -p | less
1361 libs found in cache `/etc/ld.so.cache'
        p11-kit-trust.so (libc6,x86-64) => /lib64/p11-kit-trust.so
        libzeitgeist-2.0.so.0 (libc6,x86-64) => /lib64/libzeitgeist-2.0.so.0
        libzapojit-0.0.so.0 (libc6,x86-64) => /lib64/libzapojit-0.0.so.0
        libz.so.1 (libc6,x86-64) => /lib64/libz.so.1
        libyelp.so.0 (libc6,x86-64) => /lib64/libyelp.so.0
        libyaml-0.so.2 (libc6,x86-64) => /lib64/libyaml-0.so.2
        libyajl.so.2 (libc6,x86-64) => /lib64/libyajl.so.2
        libxtables.so.10 (libc6,x86-64) => /lib64/libxtables.so.10
        libxslt.so.1 (libc6,x86-64) => /lib64/libxslt.so.1
        libxshmfence.so.1 (libc6,x86-64) => /lib64/libxshmfence.so.1
        libxml2.so.2 (libc6,x86-64) => /lib64/libxml2.so.2
        libxmlrpc_util.so.3 (libc6,x86-64) => /lib64/libxmlrpc_util.so.3
        libxmlrpc_server_cgi.so.3 (libc6,x86-64) => /lib64/libxmlrpc_server_cgi.so.3
        libxmlrpc_server_abyss.so.3 (libc6,x86-64) => /lib64/libxmlrpc_server_abyss.so.3
        libxmlrpc_server.so.3 (libc6,x86-64) => /lib64/libxmlrpc_server.so.3
        libxmlrpc_client.so.3 (libc6,x86-64) => /lib64/libxmlrpc_client.so.3
        libxmlrpc_abyss.so.3 (libc6,x86-64) => /lib64/libxmlrpc_abyss.so.3
        libxmlrpc.so.3 (libc6,x86-64) => /lib64/libxmlrpc.so.3
        libxml-security-c.so.16 (libc6,x86-64) => /lib64/libxml-security-c.so.16
        libxlutil.so.4.3 (libc6,x86-64) => /lib64/libxlutil.so.4.3
        libxklavier.so.16 (libc6,x86-64) => /lib64/libxklavier.so.16
        libxkbfile.so.1 (libc6,x86-64) => /lib64/libxkbfile.so.1
:

特定のライブラリーをロードする

特定の古いバージョンの共有ライブラリーを必要とする古いアプリケーションを実行する場合、あるいは新しく共有ライブラリーを作成する場合や共有ライブラリーの新バージョンを作成する場合には、ローダーが使用するデフォルトの検索パスを変更する必要があるかもしれません。また、/opt ツリーにインストールされる、製品特有の共有ライブラリーを使用するスクリプトの場合にも、検索パスを変更する必要があるかもしれません。

PATH 変数を設定することで実行可能プログラムの検索パスを指定できるのと同じように、コロン区切りのディレクトリー・リストに対して LD_LIBRARY_PATH 変数を設定することができます。この設定をすると、ld.so.cache に指定されたシステム・ライブラリーを検索する前に、そのディレクトリーで共有ライブラリーが検索されます。例えば、下記のようなコマンドを使用することができます。

export LD_LIBRARY_PATH=/usr/lib/oldstuff:/opt/IBM/AgentController/lib

さらに詳しい内容や、この連載の他のチュートリアルへのリンクについては「参考文献」を参照してください。

これで、Linux 上での共有ライブラリーの管理についての簡単な紹介は終わりです。

参考文献

学ぶために

議論するために

  • developerWorks コミュニティーに参加してください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者によるブログ、フォーラム、グループ、Wiki を調べることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=1024289
ArticleTitle=Linux の 101 試験対策: 共有ライブラリーの管理
publish-date=12172015