Taketoshi Sano
, (kgh12351@nifty.ne.jp
)
まずは JF にある GCC-HOWTO (v1.17/Daniel Barlow 氏, 翻訳は v1.17j2/中野さん) の中から、 関連する文章を引用します。
6.1. 共有ライブラリと static なライブラリ プログラム作成の最終段階は「リンク」と呼ばれます。全ての部品を 結合して、足りないものがないかどうか調べる作業です。 「ファイルを開く」といったような類の作業は、多くのプログラムで 行われます。したがってこのような機能を持つ「部品」はライブラリ の形で提供されています。普通の Linux システムでは、ライブラリは /lib と /usr/lib にあります(他の場所にあることもままありますが)。
つまり「ライブラリ」とは、上記の引用文で説明されているように
多くのプログラムで共通して使われるような、 汎用的な『部品』として使われるコードを集めたものです。 UNIX 上でのソフトウェア開発は 歴史上 C 言語で行なわれることが多かったため、 (基本的なコマンドやライブラリ自身の開発は、 いくつかの例外を除いてほとんど C 言語によっています) 「最も基本的な部品」を集めたライブラリの名前は "libc" と付けられています。
例えばファイルを開くための関数である fopen(3) とか、標準出力に文字を 表示するための関数である printf(3) などが "libc" ライブラリに含まれて います。
再び、 JF の GCC-HOWTO から引用します。
static なライブラリを用いる場合は、リンカはプログラムが必要と する部品を探し、出力する実行ファイルにその部品をコピーします。 共有ライブラリの場合は違った作業が行われます。 リンカは出力ファイルに「このプログラムが実行されるときには、 まずこれこれのライブラリがロードされていないといけませんよ」と いったメッセージを埋め込みます。したがって明らかに共有ライブラリを 用いる方が実行ファイルのサイズは小さくなります。 また消費するメモリやディスク容量も小さくなります。 Linux における デフォルトの振る舞いでは、共有ライブラリがあればそちらを用い、 なければ static なリンクを行います。実行ファイルを共有ライブラリ 形式にしたいのに static になってしまった場合は、正しい位置に 共有ライブラリのファイルがあって(a.outでは *.sa、 ELF では *.so です)、 それらが読み込み可能になっているかどうかをチェックしてください。
「共有ライブラリ」は、そのライブラリを使うプログラム すべてによって「共有」 (あるいは共用、原文では shared) されるものです。
リンク (実行形式作成) 時に「static」なライブラリを使用した場合は 各実行形式ファイルの内部にそのライブラリからコピーされたコードが保存されるため、 実際に動作する時はそれぞれのコードが独立にメモリーへ読み込まれます。 同じライブラリを使うプログラムを複数起動すると、まったく同じコードの部分も すべて独立にメモリーへ読み込まれるため、メモリーの使用量は起動した数に ほぼ比例して増えます。
一方「共有ライブラリ」を使用した場合、 各実行形式ファイルの内部には「メッセージ」だけが保存されており、 起動された時にそのプログラムの実行に必要な共有ライブラリが メモリー上に無ければ読み込まれますが、 同じライブラリを使う他のプログラムによって既に読み込まれていれば、 新たにメモリーへ読み込まれるのはそのプログラム固有のコードだけとなり、 メモリー使用量がずっと少なくてすみます。
libc5 環境では、通常のコマンド (/bin/sh, /bin/cp, /bin/ls など) が 動作時に使用する "libc" の実体は "/lib/libc.so.5.4.33" などのように "libc.so.5.x.y" という形式の名前が付けられたファイルです。
このファイルには "/lib/libc.so.5" という名前のリンクが 付随しており、各プログラムは動作時にこのリンクファイルを手がかりとして 実体である /lib/libc.so.5.x.y にアクセスします。
一方プログラムの make 時にはリンカ (ld) はまず /usr/lib/libc.so に アクセスします。このファイルは libc5 環境では /lib/libc.so.5 への リンクになっており、このリンク先のファイルから得られる情報が 動作時に共有ライブラリを探すための「手がかり (上記の「メッセージ」)」 として各実行形式ファイルの内部に埋め込まれます。これについて詳細を 知りたい方は、 JF の GCC-HOWTO を "soname"というキーワード で検索してみてください。
libc6 (glibc2) 環境ではちょっと話が違っていて、 "/usr/lib/libc.so" は以下のような ld のスクリプトになっています。
/* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a )
しかし、リンカ (ld) が共有ライブラリを探すためにまずこのファイル (/usr/lib/libc.so) を見るという点は libc5 の場合と同じです。 違うのは、動作時の共有ライブラリとして探しにいくべきファイルが リンクによって示されているのではなく /lib/libc.so.6 という名前で 示されている、という点ですね。
なお、libc6 (glibc2) 環境でも、libc 以外の、例えば算術演算ライブラリ の含まれている libm などでは /usr/lib/libm.so から /lib/libm.so への リンクが張られています。
ちなみに、上記の引用文中にある "a.out" や "ELF" などは 「共有ライブラリ」の構造 (種類) を示す用語です。最近の Linux システムならすべて "ELF" だと思っておけば良いでしょう。
ELF についての詳細は JF の ELF-HOWTO を読んで下さい。
さて、 "libc" が「多くのプログラムで共通して使われるような、 汎用的な『部品』として使われるコードを集めた」ライブラリの中でも、 「最も基本的な部品」を集めたライブラリであることを覚えておいて下さい。
そして、ここで「 Linux とはカーネルのことである」ということを 思い出して下さい。
"Linux システム" で使用されている「ライブラリ」の開発は、 Linux カーネルの開発とは独立しています。
Debian 1.3.1 (bo) の /usr/doc/libc5/copyright というファイルに よれば
This is the Debian GNU/Linux prepackaged version of the Linux C library. The Linux C library was adapted from, apparently, the GNU C library version 1.07.4, with additions from 4.4BSD. Please see the file `glibc' in the source distribution for complete details. Note that glibc 2.* uses a mostly rewritten library which will be used as libc6 on Linux.と書かれています。つまり、 Linux の "libc" (C library) は GNU の libc 1.07.4 をベースに、 4.4BSD からの拡張機能を加えて開発されて きたもの、ということです。これは Debian GNU/Linux によってパッケージ化された Linux C ライブラリです。 Linux C ライブラリは、 バージョン 1.07.4 の GNU C ライブラリをベースに、 4.4BSD からいくつかの機能を追加して作成されました。 詳細についてはソース配布物中の "glibc" という名前のファイルを 参照して下さい。
また glibc 2.* はほとんど完全に書き直されたライブラリであり、 これは Linux システム上で libc6 として使われるはずのものである、 ということに注意して下さい。
数年前、共有ライブラリの形式が "a.out" から "ELF" へと移行した頃は、 Linux 用 "libc" のバージョンが 4 から 5 へ移行した時期でもありました。
ためしに、 "file /lib/libc.so.?.*" を実行してみて下さい。 私のシステム (Debian 1.3.1) では
/lib/libc.so.4.6.27: \\ Linux/i386 demand-paged executable (QMAGIC), stripped /lib/libc.so.5.4.33: \\ ELF 32-bit LSB shared object, Intel 386, version 1, strippedが表示されます。
"Linux/i386 demand-paged executable (QMAGIC)" はこの共有ライブラリが "a.out" 形式であることを、また "ELF 32-bit LSB shared object, Intel 386, version 1," はこの共有ライブラリが "ELF" 形式であることを示します。
JF の GCC-HOWTO には「 6.4.3.1. ZMAGIC と QMAGIC」という節があります。 QMAGIC 以前は ZMAGIC という "a.out" 形式が使われていたようです。 つまり "a.out" 形式にはいくつかの種類があるのです。
さて、 Linux C ライブラリのバージョン 5 "libc5" までは上記のように GNU libc 1 系統をベースに開発が進められてきましたが、この "libc5" 系統は すでに新機能に関する開発が終了しています。
現在開発されているバージョンは GNU libc 2.x (Linux libc 6) です。 これが "Linux libc6" ではなく、 "glibc2" と呼ばれることが多い理由は、 従来 Linux C Library が libc5 までは GNU libc を起源に持ってはいても、 それに大幅な変更を加えた「別物」になっていたことに比べ、 新しい libc6 が「GNU libc 2 そのもの」であるということによります。
以下、 JF の Glibc 2 HOWTO (v1.5/Erig Green 氏、翻訳は岡本さん、遠藤さん) より一部引用します。
1.1. glibc2について Glibc2 は GNU C ライブラリの最新版です。現在、変更なしで動作するのは、 GNU Hurd システムと Linux i386, m68k, alpha システムです。PowerPC, MIPS, Sparc, Sparc 64, Arm 用の Linux 向けには 2.1 版で対応の予定です。 将来的には、ほかのアーキテクチャーとオペレーティングシステム用にも 順次対応の予定です。 Linux では, glibc2 は Linux libc 5 の後継、つまりlibc バージョン6 として 用いられます。Linux libc 開発者たちは libc5 を (glibc2 で) 置き換えて しまおうとしています。 2.0.6 の段階で、 glibc は十分な品質を持つと 見なされています。バージョン 2.1 (近い将来発表予定) は、より多くの 機種へ移植され、新しい機能も追加されて、中心的に用いられるように なるでしょう。
以前、 GNU Bulletin で見たのですが、例えば
<http://www.gnu.org/bulletins/bull20.html#SEC24> <http://www.gnu.org/bulletins/bull21.html#SEC20> <http://www.gnu.org/bulletins/bull22.html#SEC21>によると、 GNU libc 2.0 の開発は GNU/Hurd を主な対象として Roland McGrath 氏によって行なわれてきたが、 現在は途中から Linux/i386 を主に担当してきた Ulrich Drepper 氏が 中心となって行なわれており、 Linux/Alpha を担当する David Mosberger-Tang 氏および Richard Henderson 氏、 それに Linux/m68k を担当する Andreas Schwab 氏が協力しているようです。
また Linux libc5 の主要な開発者だった H.J.Lu 氏も glibc2 の開発に参加 しており、 libc5.4.46 のアナウンス では
Hi, Gals and Guys, The Linux C library 5 is phasing out. I am only maintaining it for very serious bug fixes only. People who want new features and other improvements should use the Linux C library 6, aka, the GNU C library 2. Please check the glibc 2 web site for details. やあ、みなさん。 Linux C ライブラリ 5 は徐々に消滅していこうとしています。私は単に 非常に重大なバグフィックスのみのために現在のコードを保守しています。 新機能やその他の改良が必要な人は、 Linux C ライブラリ 6、 つまり GNU C ライブラリ 2 を使いましょう。詳細は glibc 2 のウェブサイト を参照してください。
と書かれています。
つまり、ここで言いたいのは GNU libc 2 の開発が現状 Linux C Library の 開発者たちによって主に行なわれているということです。
これが「 Linux libc6 = GNU libc 2 」の背景です。
最近、 glibc2.0 に代わる新しいリリースとして glibc2.1 が公開されました。 alpha.gnu.org や kernel.org から入手できます。この文書の執筆時点では glibc-2.1.1-pre2 が公開された最新バージョンのようです。 現在主流の libc6 (glibc2) は、徐々にこの glibc2.1 に移行していくものと 思われます。
私もまだ実際に使ってはいませんが、 glibc2.1 を glibc2.0 と比較すると スレッドまわりなどが改善されているとのことです。なお実際にスレッド の機能 (主に SMP システムでの性能向上に有効) を利用するには linuxthreads という別パッケージが必要だそうです。注意してください。
一方、 glibc2.1 では特殊な仕掛を使って glibc2.0 とのバイナリ互換性を 維持しているらしいですが、ソースは一部変更が必要な (つまりソース互換 ではない) ようです。 また locale の扱いが glibc2.0 とは変更されている (基本的な枠組としては、 よリ完成度を高めた仕様になっているらしい) などの話も聞きます。 少し前までは日本語 (ja_JP.ujis) を扱うためには設定ファイルの修正が 必要と言われていたのですが、最近 (2.1.1) は標準でそのまま使えるように なってきたらしいです。
これからどうなっていくのか、今後もライブラリ開発の動向から目が離せませんね。
ここまで、とりあえず書けた部分だけでまとめてみましたが、 まだまだ不足している情報があるはずです。 「これも追加して欲しい」という意見をお持ちの方は 是非教えて下さい。よろしくお願いします。
この文書は LDP/JF の GCC-HOWTO, ELF-HOWTO, Glibc 2 HOWTO や その他の参考文献から得られた情報をまとめたものです。 Linux ユーザーの役に立つ文書を数多く集積し、世界に発信している LDP と JF のみなさんに感謝します。
copyrighted (c) 1999 Taketoshi Sano
この文書は GNU パブリックライセンス (GPL) バージョン 2 かそれ以降 の条件、あるいは標準的な Linux ドキュメントプロジェクト (LDP) の条件に 基づいた配布ならば自由にしていただいてかまいません。これらのライセンス はこのドキュメントが入手できるようなサイトから入手できます。LDP の条件は (翻訳をのぞく) いかなる修正も許可していません。修正されたバージョンは GPL の基でのみ配布されるものとすることが可能です。