UNIX系の実行形式ファイルは現状2つの形式があります。1つは古いa.out形式、もう1つは新しいELF形式です。 UNIX系OSは基本的にソース互換の為、実行形式のフォーマットは使用者には関係ないので、ほとんど意識されていません。 LinuxはUNIX系の中では新しい部類なのでELFに統一されているようです。
ELFフォーマットの構造 +--------------------+ + ELFヘッダ + 最初の1バイトが 0x7F , 続く3バイトがASCIIの 'E' 'L' 'F' で始まる。 + + +--------------------+ + プログラムヘッダ + 実行時にメモリへローディングするための各セクションの情報が入っているヘッダ。 + テーブル + ファイルがオブジェクトの場合は必要ありません。 +--------------------+ + + +--------------------+ + セクションヘッダ + コンパイラからリンカに渡すための各セクションの情報が入っているヘッダ。 + テーブル + ファイルが実行形式の場合は必要ありません。 +--------------------+ + + +--------------------+ + 各セクションデータ + 各セクションのデータが格納される + + + + +--------------------+ |
UNIX系のカ−ネル部は非常にコンパクトにまとめてある為、そのシステムコール類は最小限といえるものしかありません。 これを補佐しているのがライブラリの存在です。動的メモリ取得である malloc() やマルチスレッド関数,ドメイン名のIP変換などはライブラリの力により実現されています。 Windowsではシステムコールだけで十分プログラミングできますが、UNIX系ではカーネルのシステムコール+ライブラリが必要になってきます。 ただ、それによりライブラリに対する依存関係を生んでしまったことも事実で、ライブラリが異なるとトラブルが発生します。 UNIX系のメーリングリストを眺めると、カーネルのバージョンに加えてライブラリの種類,バージョンが明記されているのはその証拠といえます。
Linuxでは数多くのディストリビューションが存在します。
実行形式ファイルを違うディストリビューションに持っていっても、動作するとは限りません。
これは単にハンドルしたソフトウェアの組み合わせだけの問題だけではなく、ライブラリの相違によるものが大きいと私は考えます。
当然、ライブラリをスタティックにリンクすればその問題は生じませんが、巨大なライブラリを抱えた実行形式は明らかに効率は悪いです。
従って、バイナリ互換の実行形式を作成する条件は、
・ライブラリは使用せず、必要なものは自分で作成する。
・同一のCPUで使用する。
・同一のカーネルバージョンで使用する。
となります。
ライブラリを使用しないということは、Linuxのシステムコールを直接呼び出さなくてはなりません。 これは、DOSやWindowsのシステムコールとは訳が違います。 一番の問題点は、上位互換について全く考えられていない事です。 例えばWindowsにおいては、機能追加の為に構造体を変更する場合、違う名前に変更して新旧両方の構造体をサポートします。 ところがLinuxでは同一名称の構造体を勝手に変更してしまいます。 それも構造体の後ろに追加していく様なものではなく、メンバ変数の間に追加するという、非常に危険な手法のものもあります。 ファイルポインタ構造体のような最も重要な構造体にも見られ、「なんとかして!」という感じがします。 つまり、カーネルバージョンに依存しないバイナリ互換の実行形式を作成する為には、 カーネルバージョンにより異なる部分をすべて理解し、それらを動的に切り換える必要があり、大変であることは言うまでもありません。