ELF(Executable and Linking Format)は元々 USL(Unix System Laboratories) で開発されたバイナリ形式で、現在は Solaris や System V Release 4 が採 用しています。 Linux がかって使っていた a.out 形式に比べて、ELF 形式は 柔軟性に富むので、GCC と C ライブラリの開発者たちは Linux の標準的なバ イナリ形式を ELF にしようと決定しました。
「柔軟性に富む」というのは、標準的なアプリケーションプログラマに 2 つ の利点を与えます。
-fPIC
オプションを付けてコンパイルしたオブジェクトファイルを、
gcc -shared -Wl,-soname,libfoo.so.y -o libfoo.so.y.x *.o
というコマンドラインでリンクするだけです。
これが複雑に見えるようならば、多分 a.out 形式で同じような共有ライブラ
リを作る方法を御存知ないのでしょう。a.out 形式で共有ライブラリを作るた
めには、ライブラリを 2 度コンパイルして、ライブラリが将来使うであろう
全てのデータのための空間をあらかじめ予約し、予約されたアドレス空間は全
ての開発者間で登録しておかねばなりません(詳しくは
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.17.tar.gz
にある 20ページを超える文書をご覧ください)。
このような利点に対して、ELF を使うと多少遅くなる、という反論もあります。
1% から 5% くらい遅くなるというのが通説ですが、実際のテストが示す結果
を見ると、その差は同時に起っているさまざまなノイズに隠されてしまう程度
のもののようです。TeX や Postscript のビューワ/プリンタを持っていれば、
SunSite などから speed.comp-1.0.tar.gz
という ELF と a.out の
速度を比較した論文を入手して読むのもいいでしょう。
ELF 形式が遅くなるのは ELF のライブラリコードがポジションインデペンデ
ントでなければならないことに由来します(コンパイル時の -fPIC
オプションが意味することです)。ポジションインデペンデントであるため、
一つのレジスタをオフセット保持用に使わなけれなばならなくなります。その
ため、変数を保存するのに使えるレジスタが一つ減ってしまいます。特に
80x86 CPU では一般的に使えるレジスタが元々不足しています。速度に差が出
るのは共有ライブラリのコードに限られていることに注意してください。アプ
リケーションやカーネルでは a.out と ELF の間で速度差はありません。
ELF 化すれば何ができるかについて、多くの誤解が広まっています。
ELF は SVR4 システムと同じ形式のバイナリの`容器'ですが、だからと言って、 ELF にすれば SVR4 用のプログラムが突然 Linux でも使えるわけではありま せん。この関係はディスクフォーマットと似ているでしょう -- Linux のプロ グラムを MSDOS や Minix のフォーマットのディスクに保存したり、その逆も 可能ですが、だからといってそれぞれのシステムが互いのプログラムを実行で きるわけではありません。
(そのプログラム自身に依存しますが)他の x86 Unix 用のプログラムを Linux
で動かすことも可能かも知れませんが、この HOWTO では、そのための説明は
致しません。まず(tsx-11.mit.edu
などにある)iBCS カー
ネルモジュールについて調べることから始めましょう。
ずっと簡単に共有ライブラリが作れるようになったので、複数のプログラム間 で共通しているコードをライブラリ化すれば、結果としてより小さなプログラ ムを作成すことも可能かも知れませんが、一般的に言って、同じコンパイラオ プションを指定してバイナリが a.out よりも小さくなったなら、たまたま運 が良かったか、コンパイラのバージョンが違うためでしょう。もし「速く」なっ たら、ちょっとびっくりです。共有ライブラリを活用してプログラムが小さく なったため、スワップが減ったり、より多くのメモリを利用できるようになっ たならば、速くなることもありえますが。
この文書の手順に従えば、ELF と a.out の双方をコンパイルして動かすシス テムを構築できます。新しいプログラムはデフォルトでは ELF 形式にコンパ イルされますが、これはコマンドラインスイッチで変更できます。ELFと a.out を同時に動かした場合、両方の C ライブラリを読みこまなければなら なくなるなど、多少メモリの使用効率は悪くなります。もっとも、この差は メモリを 6Mb 積んだマシンではほとんど気づかない程度だそうですので(8Mb のマシンではもっと気づきませんでした)、あまり気にすることも無いでしょ う。何しろ、Emacs や静的リンクされた Mosaic/Netscape といったメモリを 大食いするプログラムを毎日のように 使っているでしょ? :-)
少なくともこの文脈においては。
ELF を使えるようにシステムをアップグレードするのには、主に 2 つの 理由があります:まず第一に、上述したようにプログラムがずっと柔軟にでき ること。第二に、第一とも関連しますが、だれもがそうしようとしている(あ るいは既にそうした)から。将来の C ライブラリや GCC は ELF 用のみがリリー スされますし、それ以外のプログラムの開発者たちも ELF の方へ進むはずで す。
ELF の安定性に不安を感じている人々もいます(愉快な話ではありませんが、 当然のことです)。Linux の世界で ELF は 1994 年の夏から存在していました。 その後 1995 年の 5 月か 6 月ごろ一般に公開されました。現在では、致命的 な問題は存在しないでしょう。大きなバージョンアップをする時にしばしば起 きるように、きちんと動いているシステムを壊しかねないと感じている人もい るかも知れません。でも、このバージョンアップはもはや最先端の技術ではあ りません。開発用のシステムや他の人がコンパイルしたバイナリを動かしたい 場合では、ELF は必須のものになりつつあります。カーネルを v2.0 にバージョ ンアップする際に ELF へスイッチすることを考えてください。
この HOWTO が最初に書かれた時には ELF へ移行する方法は、ここに述べ た方法一つしかありませんでした。今日では、高品質で簡単に新しいバージョ ンをインストールできるようなディストリビューションも存在します。あなた のマシンをお好みの設定にチューニングすることにかかる時間を考えると、以 下に述べるライブラリやコンパイラをごちゃごちゃにしてしまうよりは必要な データを全てバックアップして最新の Red Hat や Debian をインストールし てしまった方がいいかも知れません。
強調しておきますが、以下に述べるインストール方法はそれ自身としては簡単
な仕事です(新しいソフトウェアをダウンロードする時間を除けば一時間もあ
れば十分でしょう)が、システムが再起動できなくなるような失敗の可能性も
あちこちにあります。共有ライブラリをバージョンアップしたくなかったり、
ldconfig
や ldd
といったコマンドを御存知なかったり、
ソースコードから必要なプログラムを作成するのが面倒だったりするならば、
「より簡単な方法」を選ぶ方がいいでしょう。それも嫌な場合、とにかくこう
いう風に考えてみてください -- 「完全な ELF システム」のためには、
誰かが 全てのバイナリをその上でコンパイルし直さなければならないの
です。
それでもやりますか?