doc/ja_JP.eucJP/FAQ/hackers.sgml
1999-09-06 06:53:43 +00:00

584 lines
26 KiB
Text

<!-- $FreeBSD$ -->
<!-- The FreeBSD Japanese Documentation Project -->
<!-- Original revision: 1.16 -->
<sect>
<heading>まじめな FreeBSD ハッカーだけの話題<label id="hackers"></heading>
<p><em>訳: &a.iwasaki;.<newline>8 November 1997.</em>
<sect1>
<heading>
SNAP とか RELEASE とかは何?
</heading>
<p>現在, FreeBSD の
<url url="http://www.freebsd.org/cgi/cvsweb.cgi" name="CVS リポジトリ">
には, 三つのアクティブ/準アクティブなブランチがあります.
<itemize>
<item><bf/RELENG_2_2/ 通称 <bf/2.2-stable/ または <bf/"2.2 branch"/
<item><bf/RELENG_3/ 通称 <bf/3.x-stable/ または <bf/"3.0 branch"/
<item><bf/HEAD/ 通称 <bf/-current/ または <bf/4.0-current/
</itemize>
<p><bf/HEAD/ は他の二つと違って実際のブランチ tag ではなく,
<em/「current, 分岐していない開発本流」/のための単なるシンボリック
な定数です. 私たちはこれを <bf/-current/ と呼んでいます.
<p>現在, <bf/-current/ は 4.0 の開発本流であり,
<bf/3.0-stable/ ブランチ, つまり <bf/RELENG_3/ は
1999年1月に<bf/-current/ から分岐しています.
<p><bf/2.2-stable/ ブランチ, <bf/RELENG_2_2/ は 1996年11月に
-current から分岐しました.
<p><bf/2.1-stable/ ブランチ, <bf/RELENG_2_1_0/ は 1994年9月に
-current から分岐しました. このブランチは完全に保守されなくなっています.
<sect1>
<heading>
自分用のカスタムリリースを構築するには?<label id="custrel">
</heading>
<p>リリースを構築するには三つのことが必要です:
まず, <htmlurl url="http://www.freebsd.org/cgi/man.cgi?vn"
name="vn"> ドライバが組み込まれたカーネルを実行させている必要があります.
以下をカーネルコンフィグレーションファイルに追加し,
カーネルを作り直してください:
<verb>
pseudo-device vn #Vnode driver (turns a file into a device)
</verb>
<p>次に, CVS リポジトリ全体を手元においておく必要があります.
これを入手するには
<url url="../handbook/synching.html#CVSUP" name="CVSUP">
が使用できますが, supfile で release の名称を cvs にして
他のタグや date フィールドを削除する必要があります:
<verb>
*default prefix=/home/ncvs
*default base=/a
*default host=cvsup.FreeBSD.org
*default release=cvs
*default delete compress use-rel-suffix
## Main Source Tree
src-all
src-eBones
src-secure
# Other stuff
ports-all
www
doc-all
</verb>
<p>そして <tt/cvsup -g supfile/ を実行して自分のマシンに
CVS リポジトリ全体をコピーします...
<p>最後に, ビルド用にかなりの空き領域を用意する必要があります.
そのディレクトリを <tt>/some/big/filesystem</tt> として,
上の例で CVS リポジトリを <tt>/home/ncvs</tt> に置いたものとすると,
以下のようにしてリリースを構築します:
<verb>
setenv CVSROOT /home/ncvs # or export CVSROOT=/home/ncvs
cd /usr/src/release
make release BUILDNAME=3.0-MY-SNAP CHROOTDIR=/some/big/filesystem/release
</verb>
<p>処理が終了すると, リリース全体が <tt>/some/big/filesystem/release</tt>
に構築され, 完全な FTP インストール用の配布物が
<tt>/some/big/filesystem/release/R/ftp</tt> に作成されます.
-current 以外の開発ブランチの SNAP を自分で構築したい場合は,
<tt/RELEASETAG=SOMETAG/ を上の make release のコマンドラインに追加します.
例えば, <tt/RELEASETAG=RELENG_2_2/ とすると最新の 2.2-STABLE snapshot
が構築されます.
<sect1>
<heading>カスタムのインストールディスクを作るにはどうすればいいのですか? </heading>
<p><tt>/usr/src/release/Makefile</tt> のいろいろなターゲットとして
インストールディスク, ソース, バイナリアーカイブを作る完全な処理を
自動的におこなうようになっています. Makefile に十分な情報があります.
しかし, 実行には ``make world'' が必要で,
多くの時間とディスクの容量が必要です.
<sect1>
<heading>
``make world'' をおこなうと既存のバイナリを上書きしてしまうのですが.
</heading>
<p>ええ, それが一般的な考え方です. 名前が示しているように
``make world'' はすべてのシステムのバイナリを一から作り直しますので,
結果としてクリーンで一貫性のある環境を得ることができます
(これがそれだけ長い時間がかかる理由です).
<p>環境変数 <tt/DESTDIR/ を ``<tt/make world/'' や ``<tt/make
install/'' を実行する時に定義しておくと, 新しく作られたバイナリは
<tt>&dollar;&lcub;DESTDIR&rcub;</tt>を root とみなした
ディレクトリツリーにインストールされます.
あるでたらめな共有ライブラリの変更やプログラムの再構築によって
``<tt/make world/'' は失敗することもあります.
<sect1>
<heading>
システムブート時に ``(bus speed defaulted)'' とメッセージが出ます.
</heading>
<p>アダプテックの 1542 SCSI ホストアダプタはユーザがソフトウェア的に
バスアクセス速度の設定をおこなうことができます. 以前のバージョンの
1542 ドライバは使用可能な最大の速度を求めてアダプタを
その設定にしようとしました. これは特定のユーザのシステムでは
問題がある事がわかり, 現在ではカーネルコンフィグオプションに
``<tt/TUNE&lowbar;1542/'' が加えられています. これを使用すると,
これが働くシステムではディスクが速くなりますが,
データの衝突が起きて速くはならないシステムもあるでしょう.
<sect1>
<heading>
インターネットアクセスに制限があっても current を追いかけられますか?
<label id="ctm">
</heading>
<p>はい, <url url="../handbook/synching.html#CTM" name="CTM システム ">を
使って
ソースツリー全体のダウンロードを<tt/おこなわず/に追いかけることができます.
<sect1>
<heading>どのようにして配布ファイルを 240kバイトに分割しているのですか?</heading>
<p>比較的新しい BSDベースのシステムでは split に任意のバイト境界で
分割する ``<tt/-b/'' オプションがあります.
<p>以下は <tt>/usr/src/Makefile</tt> からの例です.
<verb>
bin-tarball:
(cd $&lcub;DISTDIR&rcub;; \
tar cf - . \
gzip --no-name -9 -c | \
split -b 240640 - \
$&lcub;RELEASEDIR&rcub;/tarballs/bindist/bin_tgz.)
</verb>
<sect1>
<heading>私はカーネルに拡張をおこないました. 誰に送ればいいですか? </heading>
<p><url url="../handbook/contrib.html"
name="ハンドブックの「貢献の仕方 (Contributing to FreeBSD)」の章">
を参照してください.
<p>あなたのアイディアに感謝します!
<sect1>
<heading>PnP ISA カードの検出と初期化はどのようにおこなうのですか? </heading>
<p><url url="mailto:uhclem@nemesis.lonestar.org"
name="Frank Durda IV"> 氏より:
<p>要点は, ホストが認識されていないボードを探す時に, すべての
PnP ボードが応答することのできる少数の I/O ポートがあるという
ことです. それにより, PnP プローブルーチンが開始したとき, PnP
ボードが存在するなら, すべての PnP ボードは自分のモデル番号を
返します. そのポートを I/O read するとプローブルーチンは
問いに対するワイアード-OR された ``yes'' を得ます. この場合は
少なくとも 1ビットが ON になります. そして, プローブルーチンは
モデル ID (Microsoft/Intel によって割り当てられています)
が X より小さいボードを ``オフライン'' にすることができます.
この操作をおこない, 問い合わせに応答しているボードがまだ
残っているかどうかを調べます. もし ``<tt/0/'' が返ってくるなら X
より大きな ID を持つボードはないことになります. 今度は ``X''
よりも小さな値を持つボードについて問い合わせます. もしあるのであれば,
プローブルーチンはモデル番号が X より小さいことを知ります.
今度は, X-(limit/4) より大きな値を持つボードをオフラインにして
問い合わせを繰り返します. この ID の範囲による準バイナリサーチを
十分繰り返すことにより, プローブルーチンはマシンに存在するすべての
PnP ボードの値を最終的に得ることができます. その繰り返しの回数は
2^64 よりはるかに少ない回数です.
<p>ID は二つの 32-bit (つまり 64bit) フィールド + 8 bit
チェックサムからなります. 最初の 32 bits はベンダの識別子です.
これは公表されてはいませんが, 同一のベンダから供給されている
異なるタイプのボードでは異なる 32-bit ベンダ ID を持つことが
できるように考えられます. 製造元を特定するだけのために 32 bits
はいくらか過剰です.
<p>下位の 32 bits はシリアル番号, イーサネットアドレスなどの
ボードを特定するものです. ベンダは上位 32 bits が異なっていない
のであれば下位 32 bits が同一である 2枚目のボードを製造することは
ありません. したがって, 同じタイプの複数のボードをマシンに
いれることができ, この場合でも 64 bits 全体ではユニークです.
<p>32 bit のフィールドはすべてを 0 にすることはできません.
これは初期化のバイナリサーチの間ワイアード-OR によって 0 ではない
ビットを参照するからです.
<p>システムがすべてのボードの与えられた ID を認識すると,
それぞれのボードに対応した処理を一つずつ (同一の I/O ポートを通して)
おこないます. そして, 利用できる割り込みの選択などのボードが必要
とするリソースを検出します. すべてのボードについてこの情報を集めます.
<p>この情報はハードディスク上の ECU ファイルなどの情報とまとめられ,
マザーボードの BIOS にも結合されます. マザーボード上のハードウェア
への ECU と BIOS PnP のサポートは通常は統合されていますが,
周辺機器については真の PnPであるとはいえません.
しかし, BIOS の情報に ECU の情報を加えて調査することで,
プローブルーチンは PnP デバイスが再配置できなくなることを
避けることができます.
<p>それから, 再度 PnP デバイスにアクセスし, I/O, DMA, IRQ,
メモリマップアドレスの設定をします. デバイスはこのアドレスに
見えるようになり, 次にリブートするまでこの位置を占めます. しかし,
あなたの望む時に移動させることが不可能であるといっている
わけではありません.
<p>以上の話では大きく単純化をしてありますが, 基本的な考え方は得
られたでしょう.
<p>マイクロソフトはボードのロジックが 対立するI/O サイクルでは
デコードしていない (訳注: おそらく read 時しかデコードされていず
write 時はポートが空いているという意味でしょう)
プライマリプリンタのステータスポートのいくつかを PnP のために
占有しました. 私は初期の PnP の提案レビュー時に IBM 純正の
プリンタボードでステータスポートの write のデコードがされている
ということに気がつきましたが, MS は ``tough (頑固, 不運,
無法な)'' と言っています. そしてプリンタのステータスポートへ
アドレスの設定のために write をおこなっています. また,
そのアドレス + <tt/0x800/と read のための 3番目の I/O ポートが
<tt/0x200/ から <tt/0x3ff/ の間のどこかに置かれるでしょう.
<sect1>
<heading>FreeBSD は, 他のアーキテクチャをサポートしないんですか? </heading>
<p>いくつかのグループの人々が, FreeBSD の他のアーキテクチャへの
移植に関心を示しており, FreeBSD/AXP (ALPHA) はこれらの成果としては
とても成功したものの一つです. FreeBSD/AXP は 3.0 スナップショット
リリースが現在 <url url="ftp://ftp.freebsd.org/pub/FreeBSD/alpha/"
name="ftp://ftp.freebsd.org/pub/FreeBSD/alpha"> から入手できます.
ALPHA への移植版が現在動く機種は増えつつあり, その中には AlphaStation,
AXPpci, PC164, Miata そして Multia といったモデルが含まれています.
この ALPHA への移植版はまだ完全なリリースとはみなされていません.
システムインストールツール一式や CDROM のインストールメディアの
配布が提供され, 適度な数の ports や packages が動くようになって
からになるでしょう.
現在のところ FreeBSD/AXP はベータクオリティのソフトウェアと
みなすべきです. 現状についての情報を得るには
<tt>&lt;freebsd-alpha@FreeBSD.ORG&gt;</tt><ref id="mailing"
name="メーリングリスト"> に参加してください.
その他に FreeBSD の SPARC アーキテクチャへの移植があります.
プロジェクトへの参加に興味がある方は
<tt>&lt;freebsd-sparc@FreeBSD.ORG&gt;</tt><ref id="mailing"
name="メーリングリスト"> に参加してください.
新しいアーキテクチャに関する一般的な議論については
<tt>&lt;freebsd-platforms@FreeBSD.ORG&gt;</tt><ref id="mailing"
name="メーリングリスト"> へ参加してください.
<sect1>
<heading>デバイスドライバを開発したので, メジャー番号が必要です. </heading>
<p>これは, 開発したドライバを公開するかどうかに依存します.
公開するのであれば, ドライバのソースコード, <tt>files.i386</tt> の変更,
コンフィグファイルのサンプル, デバイスが使うスペシャルファイルを作成する
<htmlurl url="http://www.freebsd.org/cgi/man.cgi?MAKEDEV" name="MAKEDEV">
のコードを私たちに送ってください. 公開するつもりがない場合, ライセンスの
問題により公開できない場合は, キャラクタメジャー番号 32 もしくは
ブロックメジャー番号 8 が, このような目的のために予約されています.
これらの番号を使用してください. どちらの場合であれ, ドライバに関する情報を
<tt>&lt;freebsd-hackers@FreeBSD.ORG&gt;</tt> に流して頂けると助かります.
<sect1>
<heading>代替のディレクトリ配置ポリシー</heading>
<p>
現在使われているディレクトリの配置ポリシーは, 私が 1983 年に書い
たものから全く変更されていません. 私は当初の配置ポリシーを, オリ
ジナルの fast filesystem のために書き, まったく改定していません.
このポリシーはシリンダグループを使い尽くすのを防ぐにはうまくいき
ましたが,お気づきの方もいる通り find の動作には不適切です. ほと
んどのファイルシステムの内容は, 深さ優先検索 (ftw とも呼ばれます)
によって作られたアーカイブからレストアして作成されます. この際,
ディレクトリは,シリンダグループにまたがって配置され, 以降の深さ
優先検索を行うには考え得る限り最悪の状態になります. もし作成する
ディレクトリの総数がわかっていれば, 解決方法はあります. (総数 /
シリンダグループ数)個のディレクトリをシリンダグループごとにまと
めて作成すれば良いのです. もちろん最適なディレクトリ配置になるよ
うに, 総数を予測する方法を考えなければなりません. しかし仮にシリ
ンダグループあたりのディレクトリ数を 10 くらいの小さな数に固定し
てしまったとしても, 大幅な改善が望めるでしょう. このポリシーを用
いるべきリストア作業を, 通常の作業(おそらく既存のポリシーを使用
したほうが良いでしょう)を区別するには, 10 秒間の間に作成されたディ
レクトリを最大 10 個までまとめて単一のシリンダグループに書き込む
という手順が使えるでしょう. とにかく私の結論は, そろそろ実験
を始めて見る時期だろうということです.
<sect1>
<heading>カーネルパニックを最大限に利用する</heading>
<p>
<em>[この節は, freebsd-current <ref id="mailing" name="mailing
list"> に <url url="mailto:wpaul@FreeBSD.ORG" name="Bill Paul">
が投稿したメールを, <url url="mailto:des@FreeBSD.ORG"
name="Dag-Erling Co&iuml;dan Sm&oslash;rgrav"> が校正し,括弧内のコ
メントを追加して引用したものです. ]</em>
<p>
<verb>
From: Bill Paul <wpaul@skynet.ctr.columbia.edu>
Subject: Re: the fs fun never stops
To: ben@rosengart.com
Date: Sun, 20 Sep 1998 15:22:50 -0400 (EDT)
Cc: current@FreeBSD.ORG
</verb>
<p>
<em>[&lt;ben@rosengart.com&gt; が以下のパニックメッセージを
投稿しました.]</em>
<verb>
> Fatal trap 12: page fault while in kernel mode
> fault virtual address = 0x40
> fault code = supervisor read, page not present
> instruction pointer = 0x8:0xf014a7e5
^^^^^^^^^^
> stack pointer = 0x10:0xf4ed6f24
> frame pointer = 0x10:0xf4ed6f28
> code segment = base 0x0, limit 0xfffff, type 0x1b
> = DPL 0, pres 1, def32 1, gran 1
> processor eflags = interrupt enabled, resume, IOPL = 0
> current process = 80 (mount)
> interrupt mask =
> trap number = 12
> panic: page fault
</verb>
<p>このようなメッセージが表示された場合, 問題が起きる状況を確認し
て, 情報を送るだけでは十分ではありません. 下線をつけた命令ポインタ
値は重要な値ですが, 残念ながらこの値は構成に依存します. つまり, こ
の値は使っているカーネルのイメージに依存するのです. もしスナップショッ
トなどの GENERIC カーネルを使っているのであれば, 他の人間が問題の
ある関数について追試をすることができますが, カスタマイズされたカー
ネルの場合は, 使っている本人にしか問題の起こった場所は特定できない
のです.
<p> 何をすれば良いのでしょう?
<itemize>
<item>命令ポインタ値をメモします. <tt/0x8:/ という部分は今回必
要ありません. 必要なのは <tt/0xf0xxxxxx/ という部分です.
<item>システムがリブートしたら, 以下の操作を行います:
<verb>
% nm /kernel.that.caused.the.panic | grep f0xxxxxx
</verb>
ここで, <tt/f0xxxxxx/ は命令ポインタ値です. カーネルシンボルの
テーブルは関数のエントリポイントを含み, 命令ポインタ値は,
関数内部のある点であり, 最初の点ではないため, この操作を行っても
完全に一致するものが表示されない場合もあります. この場合は,
最後の桁を省いてもういちどやってみてください. このようになりま
す:
<verb>
% nm /kernel.that.caused.the.panic | grep f0xxxxx
</verb>
これでも一致しない場合は, 桁を減らしながら何らかの出力があるま
で繰り返してください. 何か出力されたら, それがカーネルパニック
を引き起こした可能性のある関数のリストです. これは, 問題点を見付ける
正確な方法ではありませんが, 何もないよりましです.
</itemize>
<p>このようなパニックメッセージを投稿している人はよく見掛けますが,
このように, 命令ポインタ値を, カーネルシンボルテーブルの中の関数
とつき合わせて調べている人はまれです.
<p>パニックの原因を突き止める最良の方法は, クラッシュダンプをとり,
<tt/gdb(1)/ でスタックトレースを行うことです. もちろん -current
で <tt/gdb(1)/ がちゃんと動いていればですが (私は動くことを保証
できません. ELF 化された <tt/gdb(1)/ はカーネルクラッシュダンプを
正しく扱えないと言っている人がいました. 3.0 がβテストを終える前,
に調べなければいけません. さもないと CD 出荷後に大顰蹙を買うことに
なります).
<p>
どっちにしろ, 私は普通以下のようにします.
<itemize>
<item>カーネルコンフィグファイルを作ります. カーネルデバッガが
必要そうであれば options 'DDB' を加えても良いです(私は永久ルー
プが起こっていそうな場合に, ブレークポイントを設定するのに使って
います).
<item> <tt/config -g KERNELCONFIG/ としてビルドディレクトリを設
定します.
<item><tt>cd /sys/compile/KERNELCONFIG; make</tt>
<item>カーネルのコンパイルが終了するのを待ちます.
<item><tt/cp kernel kernel.debug/
<item><tt/strip -d kernel/
<item><tt/mv /kernel /kernel.orig/
<item><tt>cp kernel /</tt>
<item>reboot
</itemize>
<p> <em>[注: 現在 FreeBSD 3.x kernel はデフォルトで ELF 形式となっており,
<tt/strip -d/ の代りに <tt/strip -g/ を使う必要があります.
何らかの理由でまだ a.out 形式の kernel を使っている場合は,
<tt/strip -aout -d/ を使ってください. ]</em>
<p> 全てのデバッグシンボルを含んだカーネルを, 実際にブートする必要は
<em>ありません.</em> <tt/-g/ をつけてコンパイルされたカーネルは,
簡単に 10MB 近くの大きさになってしまいます. こんな大きなカーネル
を実際にブートする必要はありません. この大きなカーネルイメージは
後で<tt/gdb(1)/を使うときにのみ必要です(<tt/gdb(1)/ がシンボル
テーブルを必要とするため). シンボルを含んだカーネルのコピーを保
存 しておき, <tt/strip -d/ を使ってシンボルを除いたカーネルを作
成して ブートします.
<p> 確実にクラッシュダンプをとるには, <tt>/etc/rc.conf</tt> を編
集して <tt/dumpdev/ を使用しているスワップパーティションに指定す
る必 要があります. こうすると <tt/rc(8)/ スクリプトから
<tt/dumpon(8)/ コマンドが実行されクラッシュダンプ機能が有効にな
ります. 手動で <tt/dumpon(8)/ コマンドを実行してもかまいませ
ん. パニックの後, クラッシュダンプは <tt/savecore(8)/ コマンドを
使用して取り出すこと ができます. <tt/dumpdev/ が
<tt>/etc/rc.conf</tt> で設定されていれ ば, <tt/rc(8)/ スクリプト
から <tt/savecore(8)/ が自動的に実行され, クラッシュダンプを
<tt>/var/crash</tt> に保存します.
<p> 注: FreeBSD のクラッシュダンプのサイズは, ふつう物理メモリサ
イズと同じです. つまり 64MB のメモリを積んでいれば, 64MB のクラッ
シュ ダンプが生成されることになります. <tt>/var/crash</tt> に十
分な空き 容量があることを確認してください. 手動で
<tt/savecore(8)/ を実行す れば, もっと空き容量のあるディレクトリ
にクラッシュダンプを保存でき ます. <tt/options MAXMEM=(foo)/ と
いう行をカーネルコンフィグファイ ルに追加することで, カーネルの
メモリ使用量を制限できます. たとえば 128MB のメモリがある場合も,
カーネルのメモリ使用量を 16MB に制限し クラッシュダンプのサイズ
も 128MB ではなく 16MB にすることができます.
<p> クラッシュダンプを取り出せたら, 以下のように <tt/gdb(1)/ を使っ
てスタックトレースをとります:
<p>
<verb>
% gdb -k /sys/compile/KERNELCONFIG/kernel.debug /var/crash/vmcore.0
(gdb) where
</verb>
<p> 必要な情報が 1 画面に収まらないことも多いので, できれば
<tt/script(1)/ を使って出力を記録します. strip していないカーネ
ル イメージを使うことで, 全てのデバッグシンボルが参照でき, パニッ
ク の発生したカーネルのソースコードの行が表示されているはずです.
通常, 正確なクラッシュへの過程を追跡するには, 出力を最後の行から
逆方向に読まなければなりません. また <tt/gdb(1)/ を使って, 変数
や 構造体の内容を表示させ, クラッシュした時のシステムの状態を調
べられ ます.
<p> もしあなたがデバッグ狂で, 同時に別のコンピュータを利用できる
環境にあれば, <tt/gdb(1)/ をリモートデバッグに使うこともできます.
リモートデバッグを使うと, あるコンピュータ上の <tt/gdb(1)/ を使っ
て, 別のコンピュータのカーネルをデバッグできます. ブレークポイン
トの設 定, カーネルコードのステップ実行など, ふつうのプログラム
のデバッグ と変わりません. コンピュータを 2 台並べてデバッグする
チャンスには, なかなか恵まれないので, 私はまだリモートデバッグを
試したことはあり ません.
<p> <em>[Bill による注: DDB を有効にしていてカーネルがデバッガに
落ちたら, ddb のプロンプトで 'panic' と入力すれば, 強制的にパニッ
クを 起こしクラッシュダンプさせることができます. パニックの途中
で, 再び デバッガに落ちるかもしれませんが, 'continue' と入力すれ
ば, クラッシュダンプを最後まで実行させられます.]</em>
<sect1>
<heading>dlsym() が ELF 実行形式では動作しなくなります!</heading>
<p>ELF のツール類は, デフォルトでは実行形式の中に定義されている
シンボルをダイナミックリンカから見えるようにはしません.
このため, <tt>dlopen(NULL, flags)</tt> を呼び出して得られた
ハンドルに対して <tt>dlsym()</tt> で探索を行っても, こういった
シンボルを見つけられません.
<p>もし, あなたがプロセスの中心にあたる実行形式の中にある
シンボルを探索したければ,
<htmlurl url="http://www.freebsd.org/cgi/man.cgi?ld"
name="ELF リンカ"> に <tt>-export-dynamic</tt> オプションを
付けて実行形式をリンクする必要があります.
</sect1>
<sect1>
<heading>カーネルアドレス空間を大きくしたり、小さくするにはどうしたら良いのですか?</heading>
<p>
カーネルアドレス空間は, FreeBSD 3.x 上で
256MB, FreeBSD 4.x 上で 1GB がデフォルトになっています.
負荷の高いネットワークサーバ(例えば大きな FTP, HTTP サーバ)を運用する場合は,
256MB では足りないことに気付くかも知れません.
<p>
では, アドレス空間を大きくするにはどうしたら良いのでしょうか?
それには, 二つの段階を踏みます. まず,
より大きいアドレス空間を割り当てることをカーネルに知らせる必要があります.
次に, カーネルはアドレス空間の先頭にロードされるため,
アドレスの先頭が天井(訳注:カーネルアドレス空間の最下端アドレスのこと)と
ぶつかることのないように, ロードアドレスを今までより低位に設定する必要があります.
<p>
最初の段階は, <tt>src/sys/i386/include/pmap.h</tt> にある
<tt/NKPDE/ の値を増加させることで行ないます.
ここに 1GB のアドレス空間にするために, どのようにすれば良いかを示します.
<verb>
#ifndef NKPDE
#ifdef SMP
#define NKPDE 254 /* addressable number of page tables/pde's */
#else
#define NKPDE 255 /* addressable number of page tables/pde's */
#endif /* SMP */
#endif
</verb>
<p>
正確な <tt/NKPDE/ の値を計算するには,
望みのアドレス空間の大きさ(メガバイト単位)を 4 で割って,
それから UP のために 1, SMP のために 2 を引き算して下さい.
<p>
次の段階を行なうには, ロードアドレスを正確に計算することが必要です.
単純に, アドレス空間の大きさ(バイト単位)を 0x100100000 から引き算して下さい.
1GB アドレス空間の場合, その結果は 0xc0100000 になります.
そして, <tt>src/sys/i386/conf/Makefile.i386</tt> にある <tt/LOAD_ADDRESS/
に, 今計算した値を入れます. また, 次のように
<tt>src/sys/i386/conf/kernel.script</tt> のセクションの始めの方にある
ロケーションカウンタにも同じ値を入れて下さい.
<verb>
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(btext)
SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/obj/elf/home/src/tmp/usr/i386-unknown-freebsdelf/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0xc0100000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
</verb>
<p>
それが完了したら, config し直してカーネルを再構築して下さい.
おそらく, <tt/ps(1)/, <tt/top(1)/ などに不具合が出るでしょう.
それらを正常にするために, <tt/make world/ (もしくは,
変更した <tt/pmap.h/ を <tt>/usr/include/vm/</tt>
にコピーした後に, <tt/libkvm/, <tt/ps/ および <tt/top/ を
手動で再構築すること)を行なうべきです.
<p>
注意: カーネルアドレス空間の大きさは, 4 メガバイトの倍数である必要があります.
<p>
[<url url="mailto:dg@freebsd.org" name="David Greenman">
による補足: <em> カーネルアドレス空間は 2 の乗数である必要があると思いますが,
それが確かなことかどうかははっきりしていません.
昔の起動コードには, 良く高位アドレスビットのトリックが使われていたため,
少なくとも 256MB の粒度であることが想定されていたと思います.]</em>
</sect>