doc/zh_TW.Big5/FAQ/hackers.sgml
1999-09-06 06:53:43 +00:00

485 lines
20 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- $FreeBSD$ -->
<!-- The FreeBSD Documentation Project -->
<!-- Translate into Chinese by jtjang@gcn.net.tw -->
<!-- English Version: 1.11 -->
<sect>
<heading>給有心深入研究的 FreeBSD hacker <label id="hackers"></heading>
<sect1>
<heading>SNAPs 和 RELEASEs 是什麼?</heading>
<p>目前有三個活躍/半活躍的分支在 FreeBSD 的
<url url="http://www.FreeBSD.org/cgi/cvsweb.cgi" name="CVS Repository">:
<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/ 並不是真正的 branch 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>
我要怎麼作出自己的 release<label id="custrel">
</heading>
<p>做 release 包括下面這三個步驟:首先,做出有 <htmlurl
url="http://www.FreeBSD.org/cgi/man.cgi?vn" name="vn"> 這個驅動程
式的可用 kernel。把下面這一行加到 kernel 設定檔,然後做出新的
kernel 重新開機:
<verb>
pseudo-device vn #Vnode driver (turns a file into a device)
</verb>
<p>接著,你手上要有整個 CVS repository。可以參考 <url
url="../../handbook/synching.html#CVSUP" name="CVSUP"> 這篇文章,但在
supfile 中把 release 名稱設成 cvs再刪掉所有 tag 或 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/ 把所有東西都抓下來...
<p>最後,硬碟要有相當大的空間來做 release。假設你想把它放在
<tt>/some/big/filesystem</tt> 這裡,上面這個例子也把 CVS
repository 放在 <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>整個 release 會做在 <tt>/some/big/filesystem/release</tt>。結束
時 <tt>/some/big/filesystem/release/R/ftp</tt> 這個目錄可以直接用
來做為 FTP 安裝方式的來源。如果想做出 -current 以外分支的 SNAP
在上面 make release 這一行加 <tt/RELEASETAG=SOMETAG/。舉例來說,
<tt/RELEASETAG=RELENG_2_2/ 這個參數會做個即時的 2.2-STABLE snapshot。
<sect1>
<heading>怎樣才能做出自己用的安裝磁片?</heading>
<p>建立安裝磁片、還有做出 source/binary archive都是由
<tt>/usr/src/release/Makefile</tt> 裡面的各種 target 自動產生,這
個檔案裡的資訊應該足以開始。但是這個過程牽涉到 make world所以會
用到相當多的時間和硬碟空間。
<sect1>
<heading>``make world'' 把原來裝的 binary 檔都換掉了。</heading>
<p>沒錯,就是這樣子。如名字所示,``make world'' 會重新編譯系統內建
的每個 binary 檔,這樣在結束時就可確定有個一致且乾淨的環境(所以要
花上好一段時間)。
<p>在執行 ``<tt/make world/'' 或 ``<tt/make install/'' 時,如果有
設 <tt/DESTDIR/ 這個環境變數,新產生的 binary 將會裝在
<tt>&dollar;&lcub;DESTDIR&rcub;</tt> 下的同樣目錄樹中。但在某些修
改 shared library 和重建 binary 的無特定情況下,這樣做可能會使
``<tt/make world/'' 失敗。
<sect1>
<heading>
在系統開機時,出現 ``(bus speed defaulted)''。
</heading>
<p>Adaptec 1542 SCSI 卡允許使用者用軟體調整匯流排的存取速度。早
期的 1542 驅動程式試圖將它設成可用的最快速度,但後來發現在一些
機器上不能用,所以現在要在 kernel 設定中加 ``<tt/TUNE&lowbar;1542/''
這個選項來啟動這個功能。在支援的機器上用這個選項會使硬碟存取更
快,但在不支援的機器上有可能會毀掉資料。
<sect1>
<heading>
我的網路連線不快,那可以跟著 current 的發展嗎?<label id="ctm">
</heading>
<p>可以,藉著 <url url="../../handbook/synching.html#CTM" name="CTM"> 就
可以不用下傳所有的原始碼目錄樹。
<sect1>
<heading>你是怎麼把發行版本中的檔案切成一個個 240k 的小檔案?</heading>
<p>在以 BSD 為主的較新系統中split 有個 ``<tt/-b/'' 選項,是用來
把檔案以任意數目 byte 切開。
<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>我在 kernel 裡加了些新功能,要把它寄給誰?</heading>
<p>請看一下 <url url="../../handbook/contrib.html"
name="Handbook 中加入程式碼的部份">。
<p>同時也感謝你的費心!
<sect1>
<heading>ISA 的 Plug N Play 卡是怎麼偵測和初始化的?</heading>
<p>由 <url url="mailto:uhclem@nemesis.lonestar.org"
name="Frank Durda IV"> 所寫:
<p>簡單的說,當主機發出是否有 PnP 卡的詢問訊號時,所有的 PnP
會在幾個固定的 I/O port 作回應。所以當偵測 PnP 的程式開始時,它
會先問有沒有 PnP 卡在,接著所有 PnP 卡會在它所讀的 port 以自己
的型號 &num; 作回答,這樣偵測程式就會得到一個 wired-OR ``yes''
的數字,其中至少會有一個 bit 是打開的。然後偵測程式會要求型號
(由 Microsoft/Intel指定)小於 X 的卡``離線'',再去看是否還有卡回
答同樣的詢問,如果得到 ``<tt/0/'',就表示沒有型號大於 X 的卡。
現在程式會問是否有型號小於 X 的卡,如果有的話,程式再要型號大於
X-(limit/4) 的卡離線,然後重覆上面的動作。用這種類似 binary
search 的方法,在某範圍內找個幾次後,偵測程式最後會在機器中區分
出所有的 PnP 卡,搜尋次數也遠低於一個個找的 2^64 次。
<p>一張卡的 ID 由兩個 32-bit(所以上面是 2&circ;64) + 8bit 偵錯
碼組成,第一個 32 bits 是用來區分各家廠商的。這些廠商沒有出來澄
清過,但看來應假設同一家出的不同種類的卡的廠商 ID 有可能不同。
用 32 bits 只來表示不同廠商的想法實在有點過頭了。
<p>第二個 32 bits 則是型號 &num、乙太網路位址、或一些使這張卡獨
特的資料。除非第一個 32 bits 不同,否則廠商不可能作出第二個 32
bit 相同的兩張卡。所以在一台機器中可以有同樣的好幾張卡,然而他們
整個 64 bits 還是會都不一樣。
<p>這兩個 32 bit 永遠都不可能為零,這使得最開始 binary search 中
的 wired-OR 會得到一個非零數字。
<p>一旦系統區分出所有卡的 ID接著會經由同樣的 port 一個個重新啟
動每張卡,接著找出已知介面卡所需的資源、有那些可以選的 interrupt
等等。所有卡都會被掃描一次,來收集這些資料。
<p>這些資訊接著和硬碟上的 ECU 檔案、或 MLB BIOS 裡的資料結合在一
起,通常是綜合 ECU 和 MLB 裡的 BIOS PnP 資料,這些週邊並不支援真
正的 PnP然而偵測程式在檢查 BIOS 和 ECU 資料後,它可以避免 PnP
週邊和那些偵測不到的相衝突。
<p>接著再度拜訪這些 PnP 週邊,這次會把可用的 I/O、DMA、IRQ 和記
憶體映射的位址都指定給它們。這些週邊就會出現在所指定的地方,直到
下一次重新開機為止,不過也沒有人說不能把它們隨時移來移去。
<p>上面有相當多的簡化,但你應該已經了解大致的過程。
<p>Microsoft 把表示印表機狀態的幾個主要 port 拿來作 PnP他們的
邏輯是沒有一張卡會在這些地方解碼作相反的 I/O cycles。但是我找到
一款早期仍在評估 PnP 提案時的 IBM 原廠 printer board它的確去解
對這些狀態 port 的寫入資料,但是 MS ``說了就算''。所以它們的確有
對印表機狀態 port 寫入,還有讀取該位址 + <tt/0x800/、和另一個在
<tt/0x200/ 及 <tt/0x3ff/ 之間的 port。
<sect1>
<heading>FreeBSD 是否有支援 x86 以外的機器架構?</heading>
<p>有幾群人士已經表示對發展多平台 FreeBSD 的興趣,其中
FreeBSD/AXP (ALPHA) 即是其中相當成功的例子,可以在 <url
url="ftp://ftp.FreeBSD.org/pub/FreeBSD/alpha/"
name="ftp://ftp.FreeBSD.org/pub/FreeBSD/alpha"> 這裡取得它的
3.0 SNAPshot 版本。ALPHA 版的 FreeBSD 在越來越多的 ALPHA 機器上
使用,其中包括了 AlphaStation、AXPpci、PC164、Miata 和 Multia
這幾種。要等到系統安裝工具完全、能用光碟安裝、以及有足夠能用的
port/package 之後,我們才打算把它當作完整的版本,所以現在應該把
FreeBSD/AXP 當作 BETA 品質的軟體。若要相關狀況的消息,請加入
<tt>&lt;freebsd-alpha@FreeBSD.org&gt;</tt><ref id="mailing"
name="mailing list">.
也有人表示過將 FreeBSD SPARC 版本的興趣,如果你想參加這個計畫,
請加入 <tt>&lt;freebsd-sparc@FreeBSD.org&gt;
</tt><ref id="mailing" name="mailing list">。如果想要知道關於
新平台的討論,請加入 <tt>&lt;freebsd-platforms@FreeBSD.org&gt;</tt>
<ref id="mailing" name="mailing list">。
<sect1>
<heading>我剛剛寫了某個設備的驅動程式,能不能給它一個 major number
</heading>
<p>這要看你是否打算將這個驅動程式公開使用,如果是的話,請把它的原始
碼送一份給我們,還有 <tt>files.i386</tt> 修改的部份、kernel 設定
檔樣本、以及用來產生設備檔的 <htmlurl
url="http://www.FreeBSD.org/cgi/man.cgi?MAKEDEV" name="MAKEDEV">。
如果你不打算、或因為版權問題而不能公開的話,我們有特地保留
character major number 32 和 block major number 8 給這方面的使用,
直接用這兩個就好了。不論如何,我們都會很感激你能在
<tt>&lt;freebsd-hackers@FreeBSD.org&gt;</tt> 發表驅動程式的消息。
<sect1>
<heading>關於放置目錄和檔案 inode 作法上的相異</heading>
<p>在回答有關目錄放置方式不同的問題上,我在 1983 年寫好目前的作法
後就沒有再改變過,這種方式是針對原先的 FFS 檔案系統,後來也沒
有對它作任何更動。它在避免 cylinder group 被填滿這方面做得相當
成功,但是就像有些人已經注意到,它和 `find' 就配合得不大好。大
部份的檔案系統是由那些用 depth first search(aka ftw) 產生的
archive 製造出來,解出來的目錄 inode 會橫跨好幾個 cylinder
group如果以後要做 depth first search 的話,這是最糟糕的情況之
一。如果我們知道總共會產生多少目錄的話,解法是在做任何存取/寫
入動作之前,在每個 cylinder group 上先造出(所有目錄數/cylinder
greoup 的數目)這麼多的目錄。很明顯的,我們必須要有根據地去猜這
個數字,就算一個像 10 的很小固定數目也會使效率以級數成長。區分
restore (即解開上述的 archive) 和一般檔案操作的方法可以是(現在
用的演算法可能要更敏感):如果一些目錄(最多 10 個)都在 10 秒內產
生的話,那麼就把這些目錄聚集在同一個 cylinder group。不管怎樣
我的經驗指出這是一個已經充份實驗過的部份。</p>
<p>Kirk McKusick, September 1998</p>
<sect1>
<heading>如何從 kernel panic 得到最多資訊?</heading>
<p>
<em>[這節是從 <url url="mailto:wpaul@FreeBSD.org" name="Bill Paul">
在 freebsd-current <ref id="mailing" name="mailing list"> 上發表
的信中節錄,<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; 發表了下面的 panic 訊息]</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>當你看到像這樣的訊息時,只把它拷一份送上來是不夠的。我在上
面特地標明的 instruction pointer 值相當重要,不幸的是它會因設
定而不同。換句話說,這個值會跟你用的 kernel image 檔而變動。如
果是用某個 snapshot 版本的 GENERIC kernel也許其他人可以追蹤
到出問題的函式,但如果你是用自訂的 kernel那麼只有<em/你/才能
告訴我們問題出在那裡。
<p>要做的事包括這些:
<itemize>
<item>把 instruction pointer 的值記下來。注意在前面的 <tt/0x8:/
在這個情況中並不重要,我們要的是 <tt/0xf0xxxxxx/。
<item>當系統重新開機後,執行這道命令:
<verb>
% nm /(造成 panic 的 kernel 檔案) | grep f0xxxxxx
</verb>
其中 <tt/f0xxxxxx/ 就是記下來的 instruction pointer 值。有可能
不會剛好找到完整的這個字串,這是因為 kernel symbol table 裡的各
個 symbol 只是函式的進入點,但 instruction pointer 所指的位址有
可能是在函式內的某一處,而不一定在開頭。所以如果找不到整個字串,
那麼把 instruction pointer 值的最後一個數字拿掉,再試一次:
<verb>
% nm /kernel.that.caused.the.panic | grep f0xxxxx
</verb>
如果這樣也找不到,那就把另一個數字去掉再找,一直重複到找到為止,
結果是一串可能造成 panic 的函式列表。這樣比直接找到出問題的函式
來得差,但至少好過什麼都沒有。
</itemize>
<p>我常常看到人們顯示一大片 panic 訊息,但很少看到有人花一點時間
把 instruction pointer 和 kernel symbol table 中的函式比較一下。
<p>要追蹤出造成 panic 原因的最好方法是先做出 crash dump然後用
<tt/gdb(1)/ 在上面做 stack trace。當然這要靠 -current 中的
<tt/gdb(1)/ 能運作正常,然而我無法保證這一點。(記得有人說 ELF 的
<tt/gdb(1)/ 在 kernel 的 crash dump 上不能正常操作,在 3.0 脫離
BETA 階段時最好有人先檢查這方面的狀況,免得很多人在收到 3.0 光碟
後脹紅了臉。)
<p>
不管是那一種,我通常是用這個方法:
<itemize>
<item>寫好 kernel 設定檔。如果你需要用 kernel debugger在設定
檔中加上 `options DDB' 這個選項。(當我懷疑有出現無窮迴圈時,通
常會用這個來設定中斷點。)
<item>用 <tt/config -g KERNELCONFIG/ 做出用來編譯的目錄
<item><tt>cd /sys/compile/KERNELCONFIG; make</tt>
<item>等 kernel 編譯出來
<item><tt/cp kernel kernel.debug/
<item><tt/strip -d kernel/
<item><tt/mv /kernel /kernel.orig/
<item><tt>cp kernel /</tt>
<item>重新開機
</itemize>
<p> <em>[注意:現在 FreeBSD 3.x kernel 內定是 ELF 格式,所以應該
用 <tt/strip -g/ 而不是 <tt/strip -d/。如果你的 kernel 因某種原
因仍是 a.out 格式的話,則用 <tt/strip -aout -d/。]</em>
<p>注意你<em/不會/真的用包括所有 debug symbol 的 kernel 來開機,
用 <tt/-g/ 編譯出來的 kernel 大小很容易就超過 10MB。不需要用這麼
大的 kernel 開機,晚一點 <tt/gdb(1)/ 才會需要它(<tt/gdb(1)/ 會用
到裡面的 symbol table)。所以我們才會把完整的 kernel 複製一份,接
著用 <tt/strip -d/ 刪掉 debug symbol做出第二個 kernel這個才真
正拿來開機。
<p>要確定能抓到 crash dump先編輯 <tt>/etc/rc.conf</tt>,將
<tt/dumpdev/ 指到 swap 分割區。這樣 <tt/rc(8)/ 會用 <tt/dumpon(8)/
來啟動 crash dump你也可以手動用 <tt/dumpon(8)/。在 panic 之後,
crash dump 可以用 <tt/savecore(8)/ 存起來;如果 <tt>/etc/rc.conf</tt>
裡有設 <tt/dumpdev/,那麼重新開機後 <tt/rc(8)/ 會自動執行
<tt/savecore(8)/ 把 crash dump 存在 <tt>/var/crash</tt>。
<p>注意FreeBSD 的 crash dump 通常和機器裡的實際記憶體一樣大,
就像如果有 64MB 記憶體crash dump 大小就是 64MB。所以要確定
<tt>/var/crash</tt> 下有足夠的空間,或是可以手動執行 <tt/savecore(8)/
把 crash dump 放到另一個空間較夠的目錄下。另一種也許可以限制 crash
dump 的方法,是在 kernel 設定檔中用 <tt/options MAXMEM=(foo)/
將 kernel 可用的記憶體限制在合理的大小。舉例來說,如果你有 128MB
的記憶體,但是可以限制 kernel 只能用 16MB 的記憶體,這樣 crash
dump 就是 16MB 而不是 128MB 了。
<p>一旦發現有了 crash dump就可以用 <tt/gdb(1)/ 來做 stack trace
,如下所示:
<p>
<verb>
% gdb -k /sys/compile/KERNELCONFIG/kernel.debug /var/crash/vmcore.0
(gdb) where
</verb>
<p>要注意可能會出現好幾個螢幕的可用資訊,你可以用 <tt/script(1)/
把所有輸出都存起來。用包括所有 debug symbol 的 kernel 來除錯,
這樣應該可以直接顯示 panic 是發生在那一行。通常是由下往上讀 stack
strace這樣才能一個個追蹤出有那些動作引到 crash。也可以用
<tt/gdb(1)/ 把各種變數或結構的內容印出來,以檢查系統 crash 時的
實際狀態。
<p>好啦,如果你有第二台電腦而且有夠瘋狂,可以將 <tt/gdb(1)/ 設定
成遠端除錯。這樣你可以在一台機器中用 <tt/gdb(1)/ 去除錯另一台裡的
kernel可以執行的包括設定中斷點、在 kernel 原始碼中一步步執行等
等,就像在一般使用者程式上除錯一樣。由於沒有什麼機會為除錯而設置
兩台並鄰電腦,所以我還沒有這樣玩過。
<p><em>[Bill 附注:我忘了提到一點:如果你有啟動 DDB 而 kernel 也
已經進入除錯器,可以在 DDB 命令列下打 `panic',強迫產生 panic(還
有 crash dump)。也有可能在 panic 階段時再進入除錯器,如果這樣的話
,輸入 `continue',接著它就會完成 crash dump。 -ed]</em>
<sect1>
<heading>dlsym() 對 ELF 執行檔不能用!</heading>
<p>在 ELF 一系列的工具中,內定是不會讓 dynamic linker 看到執行檔
裡定義了那些 symbol。所以 <tt>dlsym()</tt> 沒有辦法用藉由呼叫
<tt>dlopen(NULL, flags)</tt> 取得的 handle用它去搜尋有那些
symbol 一定會失敗。
<p>如果你想要用 <tt>dlsym()</tt> 找出某個 process 的主執行檔中
有那些 symbol則要在 link 時對
<htmlurl url="http://www.FreeBSD.org/cgi/man.cgi?ld"
name="ELF linker"> 加上 <tt>-export-dynamic</tt> 這個參數。
<sect1>
<heading>增加或減少 kernel 能定址的空間</heading>
<p>系統的內定是FreeBSD 3.x kernel 能定址到 256 MB4.x 則是
1 GB。如果是網路負荷相當重的伺服器(就像大型 FTP 或 HTTP 伺服器)
256 MB 可能會不大夠。
<p>要怎麼增加定址空間呢? 要從兩方面著手。首先告訴 kernel 本身要
保留較大空間; 其次,既然是在定址空間的最上面載入 kernel所以還
要調低載入的位址,否則就會超過定址範圍。
<p>增加 <tt>src/sys/i386/include/pmap.h</tt> 裡的 <tt/NKPDE/ 值
便可達成第一個目標。1 GB 的定址空間會像這樣:
<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/ 的正確值,將想要的空間大小(以 megabyte 為單
位)除以 4接著單 CPU 機器減 1雙 CPU 則是減 2。
<p>要解決第二個問題,必須自行算出 kernel 被載入的位址:求出
0x100100000 減掉定址空間大小的值(以 byte 為單位),如 1 GB 大小就
是 0xc0100000。把 <tt>src/sys/i386/conf/Makefile.i386</tt> 裡的
<tt/LOAD_ADDRESS/ 設成這個值,接著在
<tt>src/sys/i386/conf/kernel.script</tt> 中,將 section 列表最前面的
location counter 設成相同的值,如下:
<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 和做出新的 kernel。在執行像 <tt/ps(1)/、
<tt/top(1)/ 這類程式時可能會碰到問題,做一次 <tt/make world/
應該就可以解決(或把改過的 <tt/pmap.h/ 拷到 <tt>/usr/include/vm/</tt>
下,再手動編譯 <tt/libkvm/、<tt/ps/ 和 <tt/top/)。
<p>注意kernel 所能定址的空間大小必須是 4 megabytes 的倍數。
<p>[<url url="mailto:dg@FreeBSD.org" name="David Greenman"> 加上
這一段:<em>我認為 kernel 定址空間大小應該是 2 的乘冪,但不大確
定這一點。舊的啟動程式會動到 high order address bits記得它假設
至少有 256 MB。]</em>
</sect>