1.12 -> 1.13	linuxemu/chapter.sgml

Submitted by:	Hiroki Sato <hrs@geocities.co.jp>
Reviewed by:	susumu-w@ops.dti.ne.jp,
		Yasuki Arasaki <arasaki@mns2.c.u-tokyo.ac.jp>
This commit is contained in:
Jun Kuriyama 1999-09-23 14:25:15 +00:00
parent 68538df73a
commit ab1643d04f
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=5716

View file

@ -2,8 +2,8 @@
The FreeBSD Documentation Project
The FreeBSD Japanese Documentation Project
Original revision: 1.12
$FreeBSD: doc/ja_JP.eucJP/books/handbook/linuxemu/chapter.sgml,v 1.2 1999/09/06 06:53:29 peter Exp $
Original revision: 1.13
$FreeBSD: doc/ja_JP.eucJP/books/handbook/linuxemu/chapter.sgml,v 1.3 1999/09/10 12:55:51 kuriyama Exp $
-->
<chapter id="linuxemu">
@ -32,20 +32,20 @@
FreeBSD では実行できません (FreeBSD で使用可能な
<filename>/proc</filename>
ファイルシステムとは仕様が異なっているためです).
また仮想8086モー ドを有効にするなど, i386
に特有なシステムコールを使っている場合も実行 できません.</para>
また仮想 8086モードを有効にするなど, i386
に特有なシステムコールを使っている場合も実行できません.</para>
<para>Linux エミュレーションの設定方法は, 使用している FreeBSD
のバージョン によって多少異なっています.</para>
のバージョンによって多少異なっています.</para>
<sect2>
<title>2.1-STABLE への Linux エミュレーションのインストール</title>
<para>2.1-STABLE の <filename>GENERIC</filename> カーネルは,
Linux との互換性を保つように構築 されていません.
Linux との互換性を保つように構築されていません.
カーネルの再構築が必要です. 再構築をおこなうには, 2つの方
法があります. 1つは,
エミュレータをカーネル自体にスタティックリンクす る方法.
エミュレータをカーネル自体にスタティックリンクする方法.
もう1つは, 動的に Linux
ローダブルカーネルモジュール(LKM)をロー
ドするようにする方法です.</para>
@ -65,15 +65,15 @@ options COMPAT_LINUX</programlisting>
<programlisting>
options SYSVSHM</programlisting>
<para>Linux のシステムコールを使用するには, 4.3BSD
のシステムコールとの互換 性が保たれていることが必要です.
以下の行が含まれていることを確認してく ださい.</para>
<para>Linux のシステムコールを使用するには, 4.3BSD と互換性のある
システムコールを備えていることが必要です.
以下の行が含まれていることを確認してください.</para>
<programlisting>
options "COMPAT_43"</programlisting>
<para>LKM
を使用せずエミュレータをカーネルにスタティックにリンクしたい場合は, 以下の行を追加します.</para>
を使用せずエミュレータをカーネルに静的リンクしたい場合は, 以下の行を追加します.</para>
<programlisting>
options LINUX</programlisting>
@ -84,10 +84,10 @@ options LINUX</programlisting>
新しいカーネルのインストールをおこなってください.</para>
<para>LKM を使用する場合は,
ローダブルモジュールをインストールしなければなり ません.
ローダブルモジュールをインストールしなければなりません.
カーネルとローダブルモジュールのバージョンが異なると, カーネル
がクラッシュする場合がありますので, 安全を期すためには,
カーネルをイン ストールするごとに, LKM
カーネルをインストールするたびに, LKM
も再インストールしてください.</para>
<screen>&prompt.root; <userinput>cd /usr/src/lkm/linux</userinput>
@ -130,7 +130,7 @@ linux</programlisting>
<title>2.2-RELEASE への Linux エミュレーションのインストール</title>
<para><literal>options LINUX</literal> や <literal>options
COMPAT_LINUX</literal> を指定する必要 はなくなりました.
COMPAT_LINUX</literal> を指定する必要はなくなりました.
Linux エミュレーションは
LKM(&ldquo;ローダブルカーネルモジュール&rdquo;) を使用して,
リブートせず簡単にインストールできます. スタートアッ
@ -193,7 +193,7 @@ options LINUX</programlisting>
<para>多くの Linux
アプリケーションはシェアードライブラリを使用しますので,
シェアードライブラリのインストールが終了しなければ,
エミュレータのイン ストールは終わったことになりません.
エミュレータのインストールは終わったことになりません.
手動でもインストールできますが, linux_lib port
を使用するのが簡単です.</para>
@ -206,7 +206,7 @@ options LINUX</programlisting>
エミュレーションは, ZMAGIC ライブラ リとリンクされている
Linux バイナリに対して, 最もうまく動作するようで す.
Slackware V2.0 などに使われている QMAGIC ライブラリだと,
エミュレー タが胸やけするかもしれません.
エミュレータが胸やけするかもしれません.
マイナーバージョンの不一致などを
報告するプログラムもありますが,
普通は 問題にならないようです.</para>
@ -480,8 +480,8 @@ libc.so.4 (DLL Jump 4.5pl26) =&gt; /lib/libc.so.4.6.29</screen>
<title>Linux の ELF バイナリをインストールする</title>
<para>ELF のバイナリを使うためには,
&ldquo;焼き印を押す(branding)&rdquo; 作業が必要になります.
焼き印を押していない ELF バイナリを実行しようとすると,
&ldquo;マークをつける(branding)&rdquo;作業が必要になります.
マークのない ELF バイナリを実行しようとすると,
以下のようなエラーメッセージを
うけとってしまうことでしょう.</para>
@ -496,7 +496,7 @@ Abort</screen>
<screen>&prompt.user; <userinput>brandelf -t Linux my-linux-elf-binary</userinput></screen>
<para>今ではGNU のツールたちが,
ELFバイナリに自動的に適切な焼き印を押すようになったので,
ELFバイナリに自動的に適切なマークを付加するようになったので,
今後はこの作業もだんだんと必要なくなってゆくでしょう.</para>
</sect2>
@ -599,14 +599,14 @@ multi on</programlisting>
</orderedlist>
<para>混乱を避けるために, ここでは Slackware だけを取り上げます.
この配布セッ トは, 多くのサブディレクトリ内にある
この配布セットは, 多くのサブディレクトリ内にある
別々のパッケージから構成されていま す. 通常,
パッケージはインストールプログラムにより自動的に制御されま
すが, &ldquo;手動で&rdquo;おこなうことも可能です.
まず配布セットの中の, <filename>contents</filename>
サブディレクトリの内容を書くにしてください. ここには多く
の小さなテキストファイルが含まれおり,
それぞれのパッケージの内容が記述 されています.
それぞれのパッケージの内容が記述されています.
必要なファイルを探している場合は, まず contents 内のテキ
ストファイルを取得し, そのファイルの中から grep
を使用して検索するのが, 最も速い方法でしょう.
@ -692,7 +692,7 @@ multi on</programlisting>
<para>gzip で圧縮された tar ファイルから必要なファイルを
<filename>/compat/linux</filename> ディ
レクトリに格納してください(必要なファイルのみを展開するか,
あるいは必 要でないファイルを後で削除してください).
あるいは必要でないファイルを後で削除してください).
これで作業は終了です.</para>
<para><emphasis>参照:</emphasis>
@ -728,8 +728,8 @@ multi on</programlisting>
<title>Mathematica ディストリビューションの展開</title>
<para>バイナリは, Wolfram から CDROM で配布されています. CDROM
には, 1ダー スほどの tar ファイルが含まれており,
それぞれサポートされているアーキテ クチャに対応しています.
には, 1ダースほどの tar ファイルが含まれており,
それぞれサポートされているアーキテクチャに対応しています.
Linux 用のファイルは, <filename>LINUX.TAR</filename> です.
例えば <filename>/usr/local/Mathematica</filename>
以下にインストールする場合は, 以下のようにしま す.</para>
@ -768,7 +768,7 @@ richc.isdn.bcm.tmc.edu 9845-03452-90255</screen>
&ldquo;machine ID&rdquo; を知らせ て登録すると,
いくつかの番号のグループからなるパスワードが送り返されて
きます. パスワードを, マシン名, ライセンス番号とともに,
mathpass ファ イルに追加します.</para>
mathpass ファイルに追加します.</para>
<para>追加は, 以下のようにおこないます.</para>
@ -783,7 +783,7 @@ richc.isdn.bcm.tmc.edu 9845-03452-90255</screen>
<para>パスワードの入力後, <command>math.install</command> では,
インストール方法を, デフォルト 設定でのインストールか,
自分で方法を指定するインストールから選ぶことが できます.
自分で方法を指定するインストールから選ぶことができます.
筆者のようにインストールプログラムを信用していない場合は, 自
分でディレクトリを指定する方を選択するでしょう.
自分で指定するインストー ルを選んだ場合, math.install
@ -792,7 +792,7 @@ richc.isdn.bcm.tmc.edu 9845-03452-90255</screen>
を作成してください. 存在しないディレクトリを指定して,
math.install が インストールに失敗した場合には,
ディレクトリを作成し, math.install を 再び実行してください.
筆者らがインストール先に選んだディレクトリは, 以 下の通りです.
筆者らがインストール先に選んだディレクトリは, 以下の通りです.
くれぐれもあらかじめ作成してから,
<command>math.install</command> で指定す
るようにしてください.</para>
@ -823,7 +823,7 @@ richc.isdn.bcm.tmc.edu 9845-03452-90255</screen>
<para>また, システムレコードファイルとして,
<filename>/tmp/math.record</filename> を使用するように
設定することもできます. このファイルには,
セッションのログが記録されま す. この設定が終了すると,
セッションのログが記録されます. この設定が終了すると,
<command>math.install</command> は残りのファイルを展開して, 必
要な場所に格納します.</para>
@ -892,7 +892,7 @@ richc.isdn.bcm.tmc.edu 9845-03452-90255</screen>
<screen><errorname>File .../Untitled-1.mb appears to be broken for OMPR.257.0</errorname></screen>
<para>今のところ原因はわかっていませんが,
このバグが影響を及ぼすのは, ノートブッ クの X window
このバグが影響を及ぼすのは, ノートブックの X window System 用
フロントエンドのみです. Mathematica エンジン本体に影響は
ありません. そのため, ``math''
によって起動されるコマンドラインのインタ
@ -903,13 +903,187 @@ richc.isdn.bcm.tmc.edu 9845-03452-90255</screen>
<title>謝辞</title>
<para>&a.sos;と&a.peter;に深く感謝します.
Linuxエミュレーションが現在の形に あるのは, 彼らのおかげです.
そして, 彼ら二人にハッパをかけて, 犬のよう に働かせた Michael
Linuxエミュレーションが現在の形にあるのは, 彼らのおかげです.
そして, 彼ら二人にハッパをかけて, 犬のように働かせた Michael
Smithに. 今やLinuxエミュレーションは, linuxよりうま
くlinuxバイナリを実行できます <!-- smiley -->:-)</para>
</sect2>
</sect1>
</chapter>
<sect1>
<title>エミュレーションはどのような原理で行なっているのですか?</title>
<para>このセクションは, ほとんどが <email>chat@FreeBSD.org</email>
メーリングリストに投稿された
Terry Lambert<email>tlambert@primenet.com</email> 氏のメール(Message ID:
<literal>&lt;199906020108.SAA07001@usr09.primenet.com&gt;</literal>)
に基づいています.
</para>
<para>FreeBSD は, &ldquo;実行クラスローダ(execution class loader)&rdquo;
と呼ばれる抽象的な機構を持っています. これは &man.execve.2
システムコールに追加される形で実装されています.
</para>
<para>FreeBSD は, シェルインタプリタやシェルスクリプトを実行するための
<literal>#!</literal> ローダを持った単一のプログラムローダではなく,
プログラムローダのリストを備えています.
</para>
<para>歴史的に言って, UNIX プラットフォームでマジックナンバ(一般的にファイル先頭の
4 ないし 8 バイト部分)の検査を行なうのはプログラムローダだけです.
プログラムローダは, それがシステムで実行できるバイナリなのか確認して,
それが確認できればバイナリローダを呼び出します.
</para>
<para>もし, それがそのシステム用のバイナリでない場合には,
&man.execve.2; システムコールの呼び出しは失敗の戻り値を返し,
シェルがシェルコマンドとして実行しようと試みるわけです.
</para>
<para>この仮定は, &ldquo;現在利用しているシェルがどのようなものであっても&rdquo;変わりません.
</para>
<para>後になって, &man.sh.1; に変更が加えられました.
それは先頭の 2 バイトを検査し, <literal>:\n</literal> だったら
シェルとして代わりに &man.csh.1; を呼び出す, というものです(この変更は
SCO が最初に行なったと記憶しているのですが,
間違いであったら指摘して下さい).
</para>
<para>現在の FreeBSD は, プログラムローダリストを走査します.
その際, 空白文字までの文字列をインタプリタとして認識する,
通常の <literal>#!</literal> ローダを用いるため,
該当するものが存在しなければ最終的に /bin/sh がロードされます.
</para>
<para>
Linux バイナリエミュレーションを行なうため, FreeBSD は
ELF バイナリを示すマジックナンバを確認します.
(ただし, この段階で FreeBSD, Solaris, Linux, そしてその他にも存在する
ELF イメージ形式を使っている OS を区別することはできません).
</para>
<para>ELF ローダは, 特殊な<emphasis>マーク(brand)</emphasis>があるかどうか探します.
このマークとは, ELF イメージのコメントセクションのことです.
SVR4/Solaris の ELF バイナリには, このセクションは存在しません.
</para>
<para>
Linux バイナリを実行するためには,
ELF バイナリに &man.brandelf.1; で説明されている
<literal>Linux</literal> のマークが
<emphasis>付けられて</emphasis>いなければなりません.
</para>
<screen>&prompt.root; <userinput>brandelf -t Linux file</userinput></screen>
<para>上のようにすることで, 指定されたファイルは
<literal>Linux</literal> のマークが付けられ,
ELF ローダが認識できるようになります.
</para>
<para>
ELF ローダが <literal>Linux</literal> マークを確認すると,
ローダは <literallayout>proc</literallayout> 構造体内の
ある一つのポインタを置き換えます. システムコールは全て,
この置き換えられたポインタ(伝統的な UNIX システムでは,
システムコールが <literallayout>sysent[]</literallayout>
構造体の配列として実装されています)を基準に呼び出されます.
またそのプロセスには, Linux カーネルモジュールに必要な
シグナルトランポリンコード(訳注:
シグナルの伝播を実現するコード)用の特殊なトラップベクタの設定や,
他の(細かな)調整のための設定が行なわれます.
</para>
<para>
Linux システムコールベクタは, さまざまなデータに加えて
カーネルモジュール内のアドレスを指す <literal>sysent[]</literal>
エントリのリストを含んでいます.
</para>
<para>
Linux バイナリがシステムコールを発行する際, トラップコードは
<literal>proc</literal> 構造体を用いてシステムコール関数ポインタを
解釈します. そして, FreeBSD ではなく Linux 用の
システムコールエントリポイントを得るわけです.
</para>
<para>
さらに Linux エミュレーションは, 状況に応じて
<emphasis>ファイルシステム本来のルートマウントポイントを置き換えて</emphasis>
ファイルの参照を行ないます.
これは, <literal>union</literal> オプションを指定して
マウントされたファイルシステム(unionfs では<emphasis>ありません!</emphasis>)が
行なっていることと同じです.
ファイルを検索する際にはまず
<filename>/compat/linux/<replaceable>original-path</replaceable></filename>
ディレクトリを, <emphasis>それから</emphasis>見つけられなかったときにのみ,
<filename>/<replaceable>original-path</replaceable></filename>
を調べます.
こうすることで, 他のバイナリを要求するバイナリの実行を可能にしています
(したがって, Linux toolchain はエミュレーション環境下で完全に動作するわけです).
またこれは, もし対応する Linux バイナリが存在しない場合に
Linux バイナリが FreeBSD バイナリをロードしたり, 実行したりすることが可能であること,
その Linux バイナリに自分自身が Linux 上で実行されていないことを
気付かせないようにする目的で, &man.uname.1; コマンドを
<filename>/compat/linux</filename> ディレクトリに
置くことができる, ということを意味します.
</para>
<para>
要するに, Linux カーネルが FreeBSD カーネルの内部に存在しているわけです.
カーネルによって提供されるサービス全ての実装の基礎となるさまざまな関数は,
FreeBSD システムコールテーブルエントリと
Linux システムコールテーブルエントリの
両方で共通に利用されています.
これらにはファイルシステム処理, 仮想メモリ処理, シグナル伝送, System V IPC
などが含まれますが,
FreeBSD バイナリは, FreeBSD <emphasis>グルー</emphasis>(訳注: glue;
二者の間を仲介するという意味)関数群,
そして Linux バイナリは Linux <emphasis>グルー</emphasis>関数群を用いる,
という点だけが異なります(過去に存在したほとんどの OS は,
自分自身のための<emphasis>グルー</emphasis>関数群しか備えていません.
前述したように, システムコールを発行する際,
各々のプロセスの <literal>proc</literal> 構造体内にある,
ローダによって動的に初期化されるポインタを参照してアドレスを得る代わりに,
静的でグローバルな <literal>sysent[]</literal> 構造体の配列に
システムコール関数のアドレスが直接格納されているのです).
</para>
<para>
さて, どちらを本来の FreeBSD ABI と呼ぶべきなのでしょうか?
実は, どちらが本来のものであるかということを論ずることに意味はありません.
基本的に, FreeBSD <emphasis>グルー</emphasis>関数群はカーネルの中に静的にリンクされていて,
Linux <emphasis>グルー</emphasis>関数群は静的にリンクすることも,
カーネルモジュールを介して利用することもできるようになっている,
という違いがあるだけ(ただしこれは現時点においての話です.
これは将来のリリースで変更される可能性がありますし,
おそらく実際に変更されるでしょう)です.
</para>
<para>
あ, 「でもこれは本当にエミュレーションと呼べるのか」って?
答えは「いいえ」です. これは一つの ABI 実装にすぎず,
エミュレーションとは異なります. エミュレータ(シミュレータでもないことを
あらかじめ断っておきましょう)が呼び出されているわけではありません.
</para>
<para>
では, どうして &ldquo;Linux エミュレーション&rdquo; と呼ぶのでしょうか?
それはもちろん FreeBSD の売りにするため <!-- smiley -->8-) でもあるのですが,
実際には, 次のような理由によります.
この機能が初めて実装された頃, 動作原理を説明する以外に
この機能を表現する言葉はありませんでした.
しかし, コードをコンパイルしたりモジュールをロードしない場合,
「FreeBSD 上で Linux バイナリを実行する」言う表現は,
厳密に考えると適切ではありません.
そこで, その際にロードされているもの自身を表現する言葉&mdash;すなわち
&ldquo;Linux エミュレータ&rdquo;が必要だったのです.
</para>
</sect1>
</chapter>
<!--
Local Variables: