ELF(Executable and Linking Format) とは元々 USL(Unix System Laboratries) で開発されたバイナリファイルのフォーマット形式のひとつで、 現在では Solaris と System V Release 4 が採用しています。Linux が今ま で使っていた a.out 形式に比べてずっと柔軟性に富むので、去年、 GCC と C ライブラリの開発者たちは、Linux でも標準のバイナリフォーマッ トを ELF にすることに決め、ELF への移行を開始しました。
「ずっと柔軟性に富む」というのは、平均的なアプリケーションプログラマにとっ て次の 2 つの利点があります。
gcc -shared -Wl,-soname,libfoo.so.y -o libfoo.so.y.x *.o
ちょっと複雑に見えるかも知れませんが、a.out フォーマットで共有ライブラ
リを作るのに比べると、ずっと簡単になっています。a.out フォーマットで共
有ライブラリを作る場合、ライブラリに将来必要になるであろう全てのデータ
について、そのアドレススペースを確保しておく必要があります。そして、そ
のアドレススペースが他の人が作っているライブラリと競合しないように登録
しておかねばなりませんでした(このあたりの話は
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.16.tar.gz
の 20 ページくらいのドキュメントに詳しく書いてあります)
ELF を使うと少し遅くなる、という反論もあります。議論を聞いていると、2% から 5% くらい遅くなるらしいのですが、私の知っている限りでは、きちんと テストした人はいないようです。もし両者を比較しているテストを御存知なら ば、ぜひ私に教えてください。
遅くなる原因は ELF のライブラリコードがポジションインデペンデント(コン
パイル時の -fPIC
オプション)になっているからで、オフセットを
記憶するためにレジスタが 1 つ使われるので、その分変数を記憶しておくレ
ジスタが減るためです。特に 80x86 CPU では、汎用レジスタが少ないために
影響が出やすいようです。
ELF にするとどうなるかについて、多くの人が誤解している点があります。
確かに、バイナリを入れている「器」は SVR4 が使っているものと同じですが、 だからといって SVR4 のプログラムが ELF を使えば突然 Linux で利用可能に なるわけではありません。この関係はプログラムとディスクフォーマットによ く似ています。つまり、Linux のプログラムを MSDOS や Minix 形式のディス クに保存したり、MSDOS や Minix のプログラムを Linux の形式のディスクに 保存することは可能ですが、だからといって、それぞれのシステムが他のシス テムのプログラムを動かせるわけではありません。SVR4 は Linux とは異な るシステムコールの使い方をしていますし、同じシステムコールでもその意味 が違っていたり、違う番号に割りあてられていたりします。
多くのプログラムの間で共通するコードをまとめて共有ライブラリを作ること が簡単になったおかげで、積極的にライブラリ化することでバイナリコードの サイズを小さくすることはできるかも知れませんけど。一般的に言って、同じ コンパイラオプションを使って、出来たバイナリが a.out に比べて小さくなっ た場合、単なる偶然かコンパイラのバージョンが違っているせいでしょう。も し「速くなった」なら、ちょっとびっくりします。もっとも、バイナリが(簡 単に作れる共有ライブラリを使って)小さくなったなら、スワッピングも少な くなるし、キャッシュに使える領域も広くなるので速くなるかも知れません。
ここに書いてある手順にしたがえば、ELF と a.out の双方をコンパイルして 動かすことのできるシステムを作ることが可能です。将来リリースされるプロ グラムは ELF 用にコンパイルされているはずですが、これもコマンドライン のスイッチで変更可能です。もし ELF と a.out のプログラムを同時に動かそ うとするならば、メモリを多少浪費することになります。また、C ライブラリも ELF 用と a.out 用の 2 種をインストールしておく必要があります。もっとも、 6MB のメモリで普通に使うかぎり、ELF と a.out が並存することによるスピー ドの低下には気づかない、という報告も聞いています(8Mb だと、もっと気づ かないでしょう)ので、あまり気にする必要はないでしょう。だって、普段か ら Emacs や静的リンクされた Mosaic/Netscape のような膨大なメモリを食う プログラムを使っているでしょ :-)
少なくとも、この文脈においては、、 と言っておけば充分でしょう。
ELF を使えるようにシステムをアップグレードするのには、主に 2 つの理由 があります:まず第一に、上述したようにプログラムがずっと柔軟にできるこ と。第二に、第一とも関連しますが、だれもが ELF へ移行しようとしている から。将来の C ライブラリや GCC は ELF 用のみがリリースされますし、そ れ以外のプログラムの開発者たちも ELF の方へ進むはずです。
対称性にとってうれしいことに、現時点では ELF へ移行しない方がいいのに も 2 つの理由があります。第一に、ELF はまだ開発の途中にあることです。 いくかのパッケージ(カーネルを含め)は、ELF としてコンパイルするためにパッ チが必要ですし、まだまだバグも残っているでしょう。例えば、Linus 自身が ELF に乗りかえるまで待つ、というのも一つの手です。
[訳注:linux 1.3.7 で kernel の ELF 化のパッチが正式に採用 されました。1.3.7 以降のカーネルでは make config の際にカーネルを ELF 化するかどうかの選択が可能です。]
二つ目の理由は、ここに記してあるインストールの手順は比較的簡単な作業で
すが(新しいソフトウェアをダウンロードする時間を除けば、一時間もあれば
充分でしょう)、それぞれの段階でもしエラーが起きればシステムの起動が不
可能になることです。共有ライブラリをバージョンアップする必然性がなく、
ldconfig
や ldd
といったコマンドに悩まされてもいない
なら、ELF で固めたディストリビューションが出るまで待って、バックアップ
を取った上で ELF 版の linux を再インストールし、必要な部分のみ戻す方が
いいかも知れません。その上で、(ダメになってもいい機械を使って)この文書
を読んで、勉強してみるのもいいかも知れません。
それでもやりますか?