Introduce the final part of Chinese(big5) FAQ, the next step I'd like to

let Simplified Chinese(GB2312) FAQ show up.

These two files was submitted by:
	J.T. Jang <jtjang@gcn.net.tw>

The translation of Handbook(new DocBook) is in progress , too.
This commit is contained in:
Foxfair Hu 1999-04-21 05:26:08 +00:00
parent 1288a84194
commit 4eccc1e987
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=4721
4 changed files with 1522 additions and 1652 deletions

View file

@ -1,58 +1,54 @@
<!-- $Id: hackers.sgml,v 1.2 1999-03-21 16:25:40 wosch Exp $ --> <!-- $Id: hackers.sgml,v 1.3 1999-04-21 05:26:07 foxfair Exp $ -->
<!-- The FreeBSD Documentation Project --> <!-- The FreeBSD Documentation Project -->
<!-- Translate into Chinese by --> <!-- Translate into Chinese by jtjang@gcn.net.tw -->
<!-- English Version: 1.11 --> <!-- English Version: 1.11 -->
<sect> <sect>
<heading>For serious FreeBSD hackers only<label id="hackers"></heading> <heading>只給正經的 FreeBSD hacker 看<label id="hackers"></heading>
<sect1> <sect1>
<heading> <heading>SNAPs 和 RELEASEs 是什麼?</heading>
What are SNAPs and RELEASEs?
</heading>
<p>There are currently three active/semi-active branches in the FreeBSD <p>目前有三個活躍/半活躍的分支在 FreeBSD 的
<url url="http://www.freebsd.org/cgi/cvsweb.cgi" name="CVS Repository">: <url url="http://www.freebsd.org/cgi/cvsweb.cgi" name="CVS Repository">:
<itemize> <itemize>
<item><bf/RELENG_2_2/ AKA <bf/2.2-stable/ AKA <bf/"2.2 branch"/ <item><bf/RELENG_2_2/ 即 <bf/2.2-stable/ 即 <bf/"2.2 branch"/
<item><bf/RELENG_3/ AKA <bf/3.x-stable/ AKA <bf/"3.0 branch"/ <item><bf/RELENG_3/ 即 <bf/3.x-stable/ 即 <bf/"3.0 branch"/
<item><bf/HEAD/ AKA <bf/-current/ AKA <bf/4.0-current/ <item><bf/HEAD/ 即 <bf/-current/ 即 <bf/4.0-current/
</itemize> </itemize>
<p><bf/HEAD/ is not an actual branch tag, like the other two, it's <p>如同其他兩個,<bf/HEAD/ 並不是真正的 branch tag它只是一個符號
simply a symbolic constant for 常數,指向 <em/"current尚未分支的發展中版本"/ ,簡記為
<em/"the current, non-branched development stream"/ which we simply <bf/-current/。
refer to as <bf/-current/.
<p>Right now, <bf/-current/ is the 4.0 development stream and the <p>以現在來說,<bf/-current/ 朝向 4.0 發展,而 <bf/3.0-stable/ 這
<bf/3.0-stable/ branch, <bf/RELENG_3/, forked off from 個分支,也就是 <bf/RELENG_3/,在 1999 年 1 月從 <bf/-current/ 分出
<bf/-current/ in Jan 1999. 來。
<p>The <bf/2.2-stable/ branch, <bf/RELENG_2_2/, departed -current in <p><bf/2.2-stable/ 這個分支,也就是 <bf/RELENG_2_2/,是在 1996 年
November 1996. 11 月從 -current 分出來。
<p>The <bf/2.1-stable/ branch, <bf/RELENG_2_1_0/, departed -current in <p><bf/2.1-stable/ 這個分支,也就是 <bf/RELENG_2_1_0/,則是在
September of 1994. This branch has been fully retired. 1994 年 9 月從 -current 分支出來,這個分支已經完全退休了。
<sect1> <sect1>
<heading> <heading>
How do I make my own custom release?<label id="custrel"> 我要怎麼作出自己的 release<label id="custrel">
</heading> </heading>
<p>To make a release you need to do three things: First, you need to <p>做 release 包括下面這三個步驟:首先,做出有 <htmlurl
be running a kernel with the <htmlurl url="http://www.freebsd.org/cgi/man.cgi?vn" name="vn"> 這個驅動程
url="http://www.freebsd.org/cgi/man.cgi?vn" name="vn"> driver configured 式的可用 kernel。把下面這一行加到 kernel 設定檔,然後做出新的
in. Add this to your kernel config file and build a new kernel: kernel 重新開機:
<verb> <verb>
pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device vn #Vnode driver (turns a file into a device)
</verb> </verb>
<p>Second, you have to have the whole CVS repository at hand. <p>接著,你手上要有整個 CVS repository。可以參考 <url
To get this you can use <url url="../../handbook/cvsup.html" name="CVSUP"> url="../handbook/cvsup.html" name="CVSUP"> 這篇文章,但在 supfile
but in your supfile set the release name to cvs and remove any tag or 中把 release 名稱設成 cvs再刪掉所有 tag 或 date 的欄位,如下:
date fields:
<verb> <verb>
*default prefix=/home/ncvs *default prefix=/home/ncvs
@ -72,12 +68,11 @@
doc-all doc-all
</verb> </verb>
<p>Then run <tt/cvsup -g supfile/ to suck all the good bits onto your <p>然後執行 <tt/cvsup -g supfile/ 把所有東西都抓下來...
box...
<p>Finally, you need a chunk of empty space to build into. Let's <p>最後,硬碟要有相當大的空間來做 release。假設你想把它放在
say it's in <tt>/some/big/filesystem</tt>, and from the example <tt>/some/big/filesystem</tt> 這裡,上面這個例子也把 CVS
above you've got the CVS repository in <tt>/home/ncvs</tt>: repository 放在 <tt>/home/ncvs</tt> 了,接著:
<verb> <verb>
setenv CVSROOT /home/ncvs # or export CVSROOT=/home/ncvs setenv CVSROOT /home/ncvs # or export CVSROOT=/home/ncvs
@ -85,70 +80,59 @@
make release BUILDNAME=3.0-MY-SNAP CHROOTDIR=/some/big/filesystem/release make release BUILDNAME=3.0-MY-SNAP CHROOTDIR=/some/big/filesystem/release
</verb> </verb>
<p>An entire release will be built in <p>整個 release 會做在 <tt>/some/big/filesystem/release</tt>。結束
<tt>/some/big/filesystem/release</tt> and you will have a full FTP-type 時 <tt>/some/big/filesystem/release/R/ftp</tt> 這個目錄可以直接用
installation in <tt>/some/big/filesystem/release/R/ftp</tt> when you're 來做為 FTP 安裝方式的來源。如果想做出 -current 以外分支的 SNAP
done. If you want to build your SNAP along some other branch than 在上面 make release 這一行加 <tt/RELEASETAG=SOMETAG/。舉例來說,
-current, you can also add <tt/RELEASETAG=SOMETAG/ to <tt/RELEASETAG=RELENG_2_2/ 這個參數會做個即時的 2.2-STABLE snapshot。
the make release command line above, e.g. <tt/RELEASETAG=RELENG_2_2/
would build an up-to-the- minute 2.2-STABLE snapshot.
<sect1> <sect1>
<heading>How do I create customized installation disks?</heading> <heading>怎樣才能做出自己用的安裝磁片?</heading>
<p>The entire process of creating installation disks and source and <p>建立安裝磁片、還有做出 source/binary archive都是由
binary archives is automated by various targets in <tt>/usr/src/release/Makefile</tt> 裡面的各種 target 自動產生,這
<tt>/usr/src/release/Makefile</tt>. The information there should 個檔案裡的資訊應該足以開始。但是這個過程牽涉到 make world所以會
be enough to get you started. However, it should be said that this 用到相當多的時間和硬碟空間。
involves doing a ``make world'' and will therefore take up a lot of
time and disk space.
<sect1> <sect1>
<heading>``make world'' clobbers my existing installed binaries.</heading> <heading>``make world'' 把原來裝的 binary 檔都換掉了。</heading>
<p>Yes, this is the general idea; as its name might suggest, <p>沒錯,就是這樣子。如名字所示,``make world'' 會重新編譯系統內建
``make world'' rebuilds every system binary from scratch, so you can be 的每個 binary 檔,這樣在結束時就可確定有個一致且乾淨的環境(所以要
certain of having a clean and consistent environment at the end (which 花上好一段時間)。
is why it takes so long).
<p>If the environment variable <tt/DESTDIR/ is defined while running <p>在執行 ``<tt/make world/'' 或 ``<tt/make install/'' 時,如果有
``<tt/make world/'' or ``<tt/make install/'', the newly-created 設 <tt/DESTDIR/ 這個環境變數,新產生的 binary 將會裝在
binaries will be deposited in a directory tree identical to the <tt>&dollar;&lcub;DESTDIR&rcub;</tt> 下的同樣目錄樹中。但在某些修
installed one, rooted at <tt>&dollar;&lcub;DESTDIR&rcub;</tt>. 改 shared library 和重建 binary 的無特定情況下,這樣做可能會使
Some random combination of shared libraries modifications and ``<tt/make world/'' 失敗。
program rebuilds can cause this to fail in ``<tt/make world/'',
however.
<sect1> <sect1>
<heading> <heading>
When my system boots, it says ``(bus speed defaulted)''. 在系統開機時,出現 ``(bus speed defaulted)''。
</heading> </heading>
<p>The Adaptec 1542 SCSI host adapters allow the user to configure <p>Adaptec 1542 SCSI 卡允許使用者用軟體調整匯流排的存取速度。早
their bus access speed in software. Previous versions of the 期的 1542 驅動程式試圖將它設成可用的最快速度,但後來發現在一些
1542 driver tried to determine the fastest usable speed and set 機器上不能用,所以現在要在 kernel 設定中加 ``<tt/TUNE&lowbar;1542/''
the adapter to that. We found that this breaks some users' 這個選項來啟動這個功能。在支援的機器上用這個選項會使硬碟存取更
systems, so you now have to define the ``<tt/TUNE&lowbar;1542/'' kernel 快,但在不支援的機器上有可能會毀掉資料。
configuration option in order to have this take place. Using it
on those systems where it works may make your disks run faster,
but on those systems where it doesn't, your data could be
corrupted.
<sect1> <sect1>
<heading> <heading>
Can I follow current with limited Internet access?<label id="ctm"> 我的網路連線不快,那可以跟著 current 的發展嗎?<label id="ctm">
</heading> </heading>
<p>Yes, you can do this <tt /without/ downloading the whole source tree <p>可以,藉著 <url url="../handbook/ctm.html" name="CTM"> 就
by using the <url url="../../handbook/ctm.html" name="CTM facility."> 可以不用下傳所有的原始碼目錄樹。
<sect1> <sect1>
<heading>How did you split the distribution into 240k files?</heading> <heading>你是怎麼把發行版本中的檔案切成一個個 240k 的小檔案?</heading>
<p>Newer BSD based systems have a ``<tt/-b/'' option to split that <p>在以 BSD 為主的較新系統中split 有個 ``<tt/-b/'' 選項,是用來
allows them to split files on arbitrary byte boundaries. 把檔案以任意數目 byte 切開。
<p>Here is an example from <tt>/usr/src/Makefile</tt>. <p>這裡是 <tt>/usr/src/Makefile</tt> 中的一個例子:
<verb> <verb>
bin-tarball: bin-tarball:
@ -160,166 +144,130 @@
</verb> </verb>
<sect1> <sect1>
<heading>I've written a kernel extension, who do I send it to?</heading> <heading>我在 kernel 裡加了些新功能,要把它寄給誰?</heading>
<p>Please take a look at <url url="../../handbook/contrib.html" <p>請看一下 <url url="../handbook/contrib.html"
name="The Handbook entry on how to submit code."> name="Handbook 中加入程式碼的部份">。
<p>And thanks for the thought! <p>同時也感謝你的費心!
<sect1> <sect1>
<heading>How are Plug N Play ISA cards detected and initialized?</heading> <heading>ISA 的 Plug N Play 卡是怎麼偵測和初始化的?</heading>
<p>By: <url url="mailto:uhclem@nemesis.lonestar.org" <p> <url url="mailto:uhclem@nemesis.lonestar.org"
name="Frank Durda IV"> name="Frank Durda IV"> 所寫:
<p>In a nutshell, there a few I/O ports that all of the PnP boards <p>簡單的說,當主機發出是否有 PnP 卡的詢問訊號時,所有的 PnP
respond to when the host asks if anyone is out there. So when 會在幾個固定的 I/O port 作回應。所以當偵測 PnP 的程式開始時,它
the PnP probe routine starts, he asks if there are any PnP boards 會先問有沒有 PnP 卡在,接著所有 PnP 卡會在它所讀的 port 以自己
present, and all the PnP boards respond with their model &num; to 的型號 &num; 作回答,這樣偵測程式就會得到一個 wired-OR ``yes''
a I/O read of the same port, so the probe routine gets a wired-OR 的數字,其中至少會有一個 bit 是打開的。然後偵測程式會要求型號
``yes'' to that question. At least one bit will be on in that (由 Microsoft/Intel指定)小於 X 的卡``離線'',再去看是否還有卡回
reply. Then the probe code is able to cause boards with board 答同樣的詢問,如果得到 ``<tt/0/'',就表示沒有型號大於 X 的卡。
model IDs (assigned by Microsoft/Intel) lower than X to go 現在程式會問是否有型號小於 X 的卡,如果有的話,程式再要型號大於
``off-line''. It then looks to see if any boards are still X-(limit/4) 的卡離線,然後重覆上面的動作。用這種類似 binary
responding to the query. If the answer was ``<tt/0/'', then search 的方法,在某範圍內找個幾次後,偵測程式最後會在機器中區分
there are no boards with IDs above X. Now probe asks if there 出所有的 PnP 卡,搜尋次數也遠低於一個個找的 2^64 次。
are any boards below ``X''. If so, probe knows there are boards
with a model numbers below X. Probe then asks for boards greater
than X-(limit/4) to go off-line. If repeats the query. By
repeating this semi-binary search of IDs-in-range enough times,
the probing code will eventually identify all PnP boards present
in a given machine with a number of iterations that is much lower
than what 2^64 would take.
<p>The IDs are two 32-bit fields (hence 2&circ;64) + 8 bit checksum. <p>一張卡的 ID 由兩個 32-bit(所以上面是 2&circ;64) + 8bit 偵錯
The first 32 bits are a vendor identifier. They never come out 碼組成,第一個 32 bits 是用來區分各家廠商的。這些廠商沒有出來澄
and say it, but it appears to be assumed that different types of 清過,但看來應假設同一家出的不同種類的卡的廠商 ID 有可能不同。
boards from the same vendor could have different 32-bit vendor 用 32 bits 只來表示不同廠商的想法實在有點過頭了。
ids. The idea of needing 32 bits just for unique manufacturers
is a bit excessive.
<p>The lower 32 bits are a serial &num;, ethernet address, something <p>第二個 32 bits 則是型號 &num、乙太網路位址、或一些使這張卡獨
that makes this one board unique. The vendor must never produce 特的資料。除非第一個 32 bits 不同,否則廠商不可能作出第二個 32
a second board that has the same lower 32 bits unless the upper bit 相同的兩張卡。所以在一台機器中可以有同樣的好幾張卡,然而他們
32 bits are also different. So you can have multiple boards of 整個 64 bits 還是會都不一樣。
the same type in the machine and the full 64 bits will still be
unique.
<p>The 32 bit groups can never be all zero. This allows the <p>這兩個 32 bit 永遠都不可能為零,這使得最開始 binary search 中
wired-OR to show non-zero bits during the initial binary search. 的 wired-OR 會得到一個非零數字。
<p>Once the system has identified all the board IDs present, it will <p>一旦系統區分出所有卡的 ID接著會經由同樣的 port 一個個重新啟
reactivate each board, one at a time (via the same I/O ports), 動每張卡,接著找出已知介面卡所需的資源、有那些可以選的 interrupt
and find out what resources the given board needs, what interrupt 等等。所有卡都會被掃描一次,來收集這些資料。
choices are available, etc. A scan is made over all the boards
to collect this information.
<p>This info is then combined with info from any ECU files on the <p>這些資訊接著和硬碟上的 ECU 檔案、或 MLB BIOS 裡的資料結合在一
hard disk or wired into the MLB BIOS. The ECU and BIOS PnP 起,通常是綜合 ECU 和 MLB 裡的 BIOS PnP 資料,這些週邊並不支援真
support for hardware on the MLB is usually synthetic, and the 正的 PnP然而偵測程式在檢查 BIOS 和 ECU 資料後,它可以避免 PnP
peripherals don't really do genuine PnP. However by examining 週邊和那些偵測不到的相衝突。
the BIOS info plus the ECU info, the probe routines can cause the
devices that are PnP to avoid those devices the probe code cannot
relocate.
<p>Then the PnP devices are visited once more and given their I/O, <p>接著再度拜訪這些 PnP 週邊,這次會把可用的 I/O、DMA、IRQ 和記
DMA, IRQ and Memory-map address assignments. The devices will 憶體映射的位址都指定給它們。這些週邊就會出現在所指定的地方,直到
then appear at those locations and remain there until the next 下一次重新開機為止,不過也沒有人說不能把它們隨時移來移去。
reboot, although there is nothing that says you can't move them
around whenever you want.
<p>There is a lot of oversimplification above, but you should get <p>上面有相當多的簡化,但你應該已經了解大致的過程。
the general idea.
<p>Microsoft took over some of the primary printer status ports to <p>Microsoft 把表示印表機狀態的幾個主要 port 拿來作 PnP他們的
do PnP, on the logic that no boards decoded those addresses for 邏輯是沒有一張卡會在這些地方解碼作相反的 I/O cycles。但是我找到
the opposing I/O cycles. I found a genuine IBM printer board 一款早期仍在評估 PnP 提案時的 IBM 原廠 printer board它的確去解
that did decode writes of the status port during the early PnP 對這些狀態 port 的寫入資料,但是 MS ``說了就算''。所以它們的確有
proposal review period, but MS said ``tough''. So they do a 對印表機狀態 port 寫入,還有讀取該位址 + <tt/0x800/、和另一個在
write to the printer status port for setting addresses, plus that <tt/0x200/ 及 <tt/0x3ff/ 之間的 port。
use that address + <tt/0x800/, and a third I/O port for reading
that can be located anywhere between <tt/0x200/ and <tt/0x3ff/.
<sect1> <sect1>
<heading>Does FreeBSD support architectures other than the x86?</heading> <heading>FreeBSD 是否有支援 x86 以外的機器架構?</heading>
<p>Several groups of people have expressed interest in working on <p>有幾群人士已經表示對發展多平台 FreeBSD 的興趣,其中
multi-architecture ports for FreeBSD and the FreeBSD/AXP (ALPHA) FreeBSD/AXP (ALPHA) 即是其中相當成功的例子,可以在 <url
port is one such effort which has been quite successful, now
available in 3.0 SNAPshot release form at <url
url="ftp://ftp.freebsd.org/pub/FreeBSD/alpha/" url="ftp://ftp.freebsd.org/pub/FreeBSD/alpha/"
name="ftp://ftp.freebsd.org/pub/FreeBSD/alpha">. The ALPHA name="ftp://ftp.freebsd.org/pub/FreeBSD/alpha"> 這裡取得它的
port currently runs on a growing number of ALPHA machine 3.0 SNAPshot 版本。ALPHA 版的 FreeBSD 在越來越多的 ALPHA 機器上
types, among them the AlphaStation, AXPpci, PC164, Miata and Multia 使用,其中包括了 AlphaStation、AXPpci、PC164、Miata 和 Multia
models. This port is not yet considered a full release and won't be 這幾種。要等到系統安裝工具完全、能用光碟安裝、以及有足夠能用的
until a full compliment of system installation tools and a distribution port/package 之後,我們才打算把它當作完整的版本,所以現在應該把
on CDROM installation media is available, including a reasonable FreeBSD/AXP 當作 BETA 品質的軟體。若要相關狀況的消息,請加入
number of working ports and packages.
FreeBSD/AXP should be considered BETA quality software at this
time. For status information, please join the
<tt>&lt;freebsd-alpha@FreeBSD.ORG&gt;</tt><ref id="mailing" <tt>&lt;freebsd-alpha@FreeBSD.ORG&gt;</tt><ref id="mailing"
name="mailing list">. name="mailing list">.
Interest has also been expressed in a port of FreeBSD to 也有人表示過將 FreeBSD SPARC 版本的興趣,如果你想參加這個計畫,
the SPARC architecture, join the <tt>&lt;freebsd-sparc@FreeBSD.ORG&gt; 請加入 <tt>&lt;freebsd-sparc@FreeBSD.ORG&gt;
</tt><ref id="mailing" name="mailing list"> if you are interested </tt><ref id="mailing" name="mailing list">。如果想要知道關於
in joining that project. For general discussion on new architectures, 新平台的討論,請加入 <tt>&lt;freebsd-platforms@FreeBSD.ORG&gt;</tt>
join the <tt>&lt;freebsd-platforms@FreeBSD.ORG&gt;</tt> <ref id="mailing" name="mailing list">。
<ref id="mailing" name="mailing list">.
<sect1> <sect1>
<heading>I need a major number for a device driver I've written.</heading> <heading>我剛剛寫了某個設備的驅動程式,能不能給它一個 major number
</heading>
<p>This depends on whether or not you plan on making the driver
publicly available. If you do, then please send us a copy of the
driver source code, plus the appropriate modifications to
<tt>files.i386</tt>, a sample configuration file entry, and the
appropriate <htmlurl url="http://www.freebsd.org/cgi/man.cgi?MAKEDEV"
name="MAKEDEV"> code to create any special files your device uses. If
you do not, or are unable to because of licensing restrictions, then
character major number 32 and block major number 8 have been reserved
specifically for this purpose; please use them. In any case, we'd
appreciate hearing about your driver on
<tt>&lt;freebsd-hackers@FreeBSD.ORG&gt;</tt>.
<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> <sect1>
<heading>Alternative layout policies for directories</heading> <heading>關於放置目錄和檔案 inode 作法上的相異</heading>
<p> <p>在回答有關目錄放置方式不同的問題上,我在 1983 年寫好目前的作法
In answer to the question of alternative layout policies for 後就沒有再改變過,這種方式是針對原先的 FFS 檔案系統,後來也沒
directories, the scheme that is currently in use is unchanged 有對它作任何更動。它在避免 cylinder group 被填滿這方面做得相當
from what I wrote in 1983. I wrote that policy for the original 成功,但是就像有些人已經注意到,它和 `find' 就配合得不大好。大
fast filesystem, and never revisited it. It works well at keeping 部份的檔案系統是由那些用 depth first search(aka ftw) 產生的
cylinder groups from filling up. As several of you have noted, archive 製造出來,解出來的目錄 inode 會橫跨好幾個 cylinder
it works poorly for find. Most filesystems are created from group如果以後要做 depth first search 的話,這是最糟糕的情況之
archives that were created by a depth first search (aka ftw). 一。如果我們知道總共會產生多少目錄的話,解法是在做任何存取/寫
These directories end up being striped across the cylinder groups 入動作之前,在每個 cylinder group 上先造出(所有目錄數/cylinder
thus creating a worst possible senario for future depth first greoup 的數目)這麼多的目錄。很明顯的,我們必須要有根據地去猜這
searches. If one knew the total number of directories to be 個數字,就算一個像 10 的很小固定數目也會使效率以級數成長。區分
created, the solution would be to create (total / fs_ncg) per restore (即解開上述的 archive) 和一般檔案操作的方法可以是(現在
cylinder group before moving on. Obviously, one would have to 用的演算法可能要更敏感):如果一些目錄(最多 10 個)都在 10 秒內產
create some heuristic to guess at this number. Even using a 生的話,那麼就把這些目錄聚集在同一個 cylinder group。不管怎樣
small fixed number like say 10 would make an order of magnitude 我的經驗指出這是一個已經充份實驗過的部份。</p>
improvement. To differentiate restores from normal operation
(when the current algorithm is probably more sensible), you
could use the clustering of up to 10 if they were all done
within a ten second window. Anyway, my conclusion is that this
is an area ripe for experimentation.</p>
<p>Kirk McKusick, September 1998</p> <p>Kirk McKusick, September 1998</p>
<sect1> <sect1>
<heading>Making the most of a kernel panic</heading> <heading>如何從 kernel panic 得到最多資訊?</heading>
<p> <p>
<em>[This section was extracted from a mail written by <url <em>[這節是從 <url url="mailto:wpaul@FreeBSD.ORG" name="Bill Paul">
url="mailto:wpaul@FreeBSD.ORG" name="Bill Paul"> on the 在 freebsd-current <ref id="mailing" name="mailing list"> 上發表
freebsd-current <ref id="mailing" name="mailing list"> by <url 的信中節錄,<url url="mailto:des@FreeBSD.ORG"
url="mailto:des@FreeBSD.ORG" name="Dag-Erling Co&iuml;dan name="Dag-Erling Co&iuml;dan Sm&oslash;rgrav"> 修正了打字錯誤、再
Sm&oslash;rgrav">, who fixed a few typos and added the bracketed 加上括弧裡的注解。]</em>
comments]</em>
<p> <p>
<verb> <verb>
@ -331,8 +279,7 @@ Cc: current@FreeBSD.ORG
</verb> </verb>
<p> <p>
<em>[&lt;ben@rosengart.com&gt; posted the following panic <em>[&lt;ben@rosengart.com&gt; 發表了下面的 panic 訊息]</em>
message]</em>
<verb> <verb>
> Fatal trap 12: page fault while in kernel mode > Fatal trap 12: page fault while in kernel mode
> fault virtual address = 0x40 > fault virtual address = 0x40
@ -350,112 +297,93 @@ Cc: current@FreeBSD.ORG
> panic: page fault > panic: page fault
</verb> </verb>
<p> [When] you see a message like this, it's not enough to just <p>當你看到像這樣的訊息時,只把它拷一份送上來是不夠的。我在上
reproduce it and send it in. The instruction pointer value that 面特地標明的 instruction pointer 值相當重要,不幸的是它會因設
I highlighted up there is important; unfortunately, it's also 定而不同。換句話說,這個值會跟你用的 kernel image 檔而變動。如
configuration dependent. In other words, the value varies 果是用某個 snapshot 版本的 GENERIC kernel也許其他人可以追蹤
depending on the exact kernel image that you're using. If you're 到出問題的函式,但如果你是用自訂的 kernel那麼只有<em/你/才能
using a GENERIC kernel image from one of the snapshots, then 告訴我們問題出在那裡。
it's possible for somebody else to track down the offending
function, but if you're running a custom kernel then only
<em/you/ can tell us where the fault occured.
<p> What you should do is this: <p>要做的事包括這些:
<itemize> <itemize>
<item>Write down the instruction pointer value. Note that the <item>把 instruction pointer 的值記下來。注意在前面的 <tt/0x8:/
<tt/0x8:/ part at the begining is not significant in this case: 在這個情況中並不重要,我們要的是 <tt/0xf0xxxxxx/。
it's the <tt/0xf0xxxxxx/ part that we want.
<item>When the system reboots, do the following: <item>當系統重新開機後,執行這道命令:
<verb> <verb>
% nm /kernel.that.caused.the.panic | grep f0xxxxxx % nm /(造成 panic 的 kernel 檔案) | grep f0xxxxxx
</verb> </verb>
where <tt/f0xxxxxx/ is the instruction pointer value. The 其中 <tt/f0xxxxxx/ 就是記下來的 instruction pointer 值。有可能
odds are you will not get an exact match since the symbols 不會剛好找到完整的這個字串,這是因為 kernel symbol table 裡的各
in the kernel symbol table are for the entry points of 個 symbol 只是函式的進入點,但 instruction pointer 所指的位址有
functions and the instruction pointer address will be 可能是在函式內的某一處,而不一定在開頭。所以如果找不到整個字串,
somewhere inside a function, not at the start. If you don't 那麼把 instruction pointer 值的最後一個數字拿掉,再試一次:
get an exact match, omit the last digit from the instruction
pointer value and try again, i.e.:
<verb> <verb>
% nm /kernel.that.caused.the.panic | grep f0xxxxx % nm /kernel.that.caused.the.panic | grep f0xxxxx
</verb> </verb>
If that doesn't yield any results, chop off another digit. 如果這樣也找不到,那就把另一個數字去掉再找,一直重複到找到為止,
Repeat until you get some sort of output. The result will be 結果是一串可能造成 panic 的函式列表。這樣比直接找到出問題的函式
a possible list of functions which caused the panic. This is 來得差,但至少好過什麼都沒有。
a less than exact mechanism for tracking down the point of
failure, but it's better than nothing.
</itemize> </itemize>
<p> I see people constantly show panic messages like this but <p>我常常看到人們顯示一大片 panic 訊息,但很少看到有人花一點時間
rarely do I see someone take the time to match up the 把 instruction pointer 和 kernel symbol table 中的函式比較一下。
instruction pointer with a function in the kernel symbol table.
<p> The best way to track down the cause of a panic is by <p>要追蹤出造成 panic 原因的最好方法是先做出 crash dump然後用
capturing a crash dump, then using <tt/gdb(1)/ to to a stack <tt/gdb(1)/ 在上面做 stack trace。當然這要靠 -current 中的
trace on the crash dump. Of course, this depends on <tt/gdb(1)/ <tt/gdb(1)/ 能運作正常,然而我無法保證這一點。(記得有人說 ELF 的
in -current working correctly, which I can't guarantee (I recall <tt/gdb(1)/ 在 kernel 的 crash dump 上不能正常操作,在 3.0 脫離
somebody saying that the new ELF-ized <tt/gdb(1)/ didn't handle BETA 階段時最好有人先檢查這方面的狀況,免得很多人在收到 3.0 光碟
kernel crash dumps correctly: somebody should check this before 後脹紅了臉。)
3.0 goes out of beta or there'll be a lot of red faces after the
CDs ship).
<p> <p>
In any case, the method I normally use is this: 不管是那一種,我通常是用這個方法:
<itemize> <itemize>
<item>Set up a kernel config file, optionally adding 'options DDB' if you <item>寫好 kernel 設定檔。如果你需要用 kernel debugger在設定
think you need the kernel debugger for something. (I use this mainly 檔中加上 `options DDB' 這個選項。(當我懷疑有出現無窮迴圈時,通
for setting beakpoints if I suspect an infinite loop condition of 常會用這個來設定中斷點。)
some kind.) <item>用 <tt/config -g KERNELCONFIG/ 做出用來編譯的目錄
<item>Use <tt/config -g KERNELCONFIG/ to set up the build directory.
<item><tt>cd /sys/compile/KERNELCONFIG; make</tt> <item><tt>cd /sys/compile/KERNELCONFIG; make</tt>
<item>Wait for kernel to finish compiling. <item>等 kernel 編譯出來
<item><tt/cp kernel kernel.debug/ <item><tt/cp kernel kernel.debug/
<item><tt/strip -d kernel/ <item><tt/strip -d kernel/
<item><tt/mv /kernel /kernel.orig/ <item><tt/mv /kernel /kernel.orig/
<item><tt>cp kernel /</tt> <item><tt>cp kernel /</tt>
<item>reboot <item>重新開機
</itemize> </itemize>
<p> <em>[Note: Now that FreeBSD 3.x kernels are Elf by default, <p> <em>[注意:現在 FreeBSD 3.x kernel 內定是 ELF 格式,所以應該
you should use <tt/strip -g/ instead of <tt/strip -d/. If for some 用 <tt/strip -g/ 而不是 <tt/strip -d/。如果你的 kernel 因某種原
reason your kernel is still a.out, use <tt/strip -aout -d/.]</em> 因仍是 a.out 格式的話,則用 <tt/strip -aout -d/。]</em>
<p> Note that YOU DO <em/NOT/ WANT TO ACTUALLY BOOT THE KERNEL <p>注意你<em/不會/真的用包括所有 debug symbol 的 kernel 來開機,
WITH ALL THE DEBUG SYMBOLS IN IT. A kernel compiled with <tt/-g/ 用 <tt/-g/ 編譯出來的 kernel 大小很容易就超過 10MB。不需要用這麼
can easily be close to 10MB in size. You don't have to actually 大的 kernel 開機,晚一點 <tt/gdb(1)/ 才會需要它(<tt/gdb(1)/ 會用
boot this massive image: you only need it later for <tt/gdb(1)/ 到裡面的 symbol table)。所以我們才會把完整的 kernel 複製一份,接
(<tt/gdb(1)/ wants the symbol table). Instead, you want to keep 著用 <tt/strip -d/ 刪掉 debug symbol做出第二個 kernel這個才真
a copy of the full image and create a second image with the 正拿來開機。
debug symbols stripped out using <tt/strip -d/. It is this
second stripped image that you want to boot.
<p> To make sure you capture a crash dump, you need edit <p>要確定能抓到 crash dump先編輯 <tt>/etc/rc.conf</tt>,將
<tt>/etc/rc.conf</tt> and set <tt/dumpdev/ to point to your swap <tt/dumpdev/ 指到 swap 分割區。這樣 <tt/rc(8)/ 會用 <tt/dumpon(8)/
partition. This will cause the <tt/rc(8)/ scripts to use the 來啟動 crash dump你也可以手動用 <tt/dumpon(8)/。在 panic 之後,
<tt/dumpon(8)/ command to enable crash dumps. You can also run crash dump 可以用 <tt/savecore(8)/ 存起來;如果 <tt>/etc/rc.conf</tt>
<tt/dumpon(8)/ manually. After a panic, the crash dump can be 裡有設 <tt/dumpdev/,那麼重新開機後 <tt/rc(8)/ 會自動執行
recovered using <tt/savecore(8)/; if <tt/dumpdev/ is set in <tt/savecore(8)/ 把 crash dump 存在 <tt>/var/crash</tt>。
<tt>/etc/rc.conf</tt>, the <tt/rc(8)/ scripts will run
<tt/savecore(8)/ automatically and put the crash dump in
<tt>/var/crash</tt>.
<p> NOTE: FreeBSD crash dumps are usually the same size as the <p>注意FreeBSD 的 crash dump 通常和機器裡的實際記憶體一樣大,
physical RAM size of your machine. That is, if you have 64MB of 就像如果有 64MB 記憶體crash dump 大小就是 64MB。所以要確定
RAM, you will get a 64MB crash dump. Therefore you must make sure <tt>/var/crash</tt> 下有足夠的空間,或是可以手動執行 <tt/savecore(8)/
there's enough space in <tt>/var/crash</tt> to hold the dump. 把 crash dump 放到另一個空間較夠的目錄下。另一種也許可以限制 crash
Alternatively, you run <tt/savecore(8)/ manually and have it dump 的方法,是在 kernel 設定檔中用 <tt/options MAXMEM=(foo)/
recover the crash dump to another directory where you have more 將 kernel 可用的記憶體限制在合理的大小。舉例來說,如果你有 128MB
room. It's possible to limit the size of the crash dump by using 的記憶體,但是可以限制 kernel 只能用 16MB 的記憶體,這樣 crash
<tt/options MAXMEM=(foo)/ to set the amount of memory the kernel dump 就是 16MB 而不是 128MB 了。
will use to something a little more sensible. For example, if
you have 128MB of RAM, you can limit the kernel's memory usage
to 16MB so that your crash dump size will be 16MB instead of
128MB.
<p> Once you have recovered the crash dump, you can get a stack <p>一旦發現有了 crash dump就可以用 <tt/gdb(1)/ 來做 stack trace
trace with <tt/gdb(1)/ as follows: ,如下所示:
<p> <p>
<verb> <verb>
@ -463,30 +391,94 @@ Cc: current@FreeBSD.ORG
(gdb) where (gdb) where
</verb> </verb>
<p> Note that there may be several screens worth of information; <p>要注意可能會出現好幾個螢幕的可用資訊,你可以用 <tt/script(1)/
ideally you should use <tt/script(1)/ to capture all of them. 把所有輸出都存起來。用包括所有 debug symbol 的 kernel 來除錯,
Using the unstripped kernel image with all the debug symbols 這樣應該可以直接顯示 panic 是發生在那一行。通常是由下往上讀 stack
should show the exact line of kernel source code where the panic strace這樣才能一個個追蹤出有那些動作引到 crash。也可以用
occured. Usually you have to read the stack trace from the <tt/gdb(1)/ 把各種變數或結構的內容印出來,以檢查系統 crash 時的
bottom up in order to trace the exact sequence of events that 實際狀態。
lead to the crash. You can also use <tt/gdb(1)/ to print out the
contents of various variables or structures in order to examine
the system state at the time of the crash.
<p> Now, if you're really insane and have a second computer, you <p>好啦,如果你有第二台電腦而且有夠瘋狂,可以將 <tt/gdb(1)/ 設定
can also configure <tt/gdb(1)/ to do remote debugging such that 成遠端除錯。這樣你可以在一台機器中用 <tt/gdb(1)/ 去除錯另一台裡的
you can use <tt/gdb(1)/ on one system to debug the kernel on kernel可以執行的包括設定中斷點、在 kernel 原始碼中一步步執行等
another system, including setting breakpoints, single-stepping 等,就像在一般使用者程式上除錯一樣。由於沒有什麼機會為除錯而設置
through the kernel code, just like you can do with a normal 兩台並鄰電腦,所以我還沒有這樣玩過。
user-mode program. I haven't played with this yet as I don't
often have the chance to set up two machines side by side for
debugging purposes.
<p> <em>[Bill adds: "I forgot to mention one thing: if you have <p><em>[Bill 附注:我忘了提到一點:如果你有啟動 DDB 而 kernel 也
DDB enabled and the kernel drops into the debugger, you can 已經進入除錯器,可以在 DDB 命令列下打 `panic',強迫產生 panic(還
force a panic (and a crash dump) just by typing 'panic' at the 有 crash dump)。也有可能在 panic 階段時再進入除錯器,如果這樣的話
ddb prompt. It may stop in the debugger again during the panic ,輸入 `continue',接著它就會完成 crash dump。 -ed]</em>
phase. If it does, type 'continue' and it will finish the 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/ 設成這個值,接著將 section 列表最前面的
location counter 設成相同的值(譯注:在
<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 和做出新的 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><em>[<url url="mailto:dg@freebsd.org" name="David Greenman">
加上這一段:我認為 kernel 定址空間大小應該是 2 的乘冪,但不大確
定這一點。舊的啟動程式會動到 high order address bits記得它假設
至少有 256 MB。]</em>
</sect> </sect>

File diff suppressed because it is too large Load diff

View file

@ -1,58 +1,54 @@
<!-- $Id: hackers.sgml,v 1.2 1999-03-21 16:25:40 wosch Exp $ --> <!-- $Id: hackers.sgml,v 1.3 1999-04-21 05:26:07 foxfair Exp $ -->
<!-- The FreeBSD Documentation Project --> <!-- The FreeBSD Documentation Project -->
<!-- Translate into Chinese by --> <!-- Translate into Chinese by jtjang@gcn.net.tw -->
<!-- English Version: 1.11 --> <!-- English Version: 1.11 -->
<sect> <sect>
<heading>For serious FreeBSD hackers only<label id="hackers"></heading> <heading>只給正經的 FreeBSD hacker 看<label id="hackers"></heading>
<sect1> <sect1>
<heading> <heading>SNAPs 和 RELEASEs 是什麼?</heading>
What are SNAPs and RELEASEs?
</heading>
<p>There are currently three active/semi-active branches in the FreeBSD <p>目前有三個活躍/半活躍的分支在 FreeBSD 的
<url url="http://www.freebsd.org/cgi/cvsweb.cgi" name="CVS Repository">: <url url="http://www.freebsd.org/cgi/cvsweb.cgi" name="CVS Repository">:
<itemize> <itemize>
<item><bf/RELENG_2_2/ AKA <bf/2.2-stable/ AKA <bf/"2.2 branch"/ <item><bf/RELENG_2_2/ 即 <bf/2.2-stable/ 即 <bf/"2.2 branch"/
<item><bf/RELENG_3/ AKA <bf/3.x-stable/ AKA <bf/"3.0 branch"/ <item><bf/RELENG_3/ 即 <bf/3.x-stable/ 即 <bf/"3.0 branch"/
<item><bf/HEAD/ AKA <bf/-current/ AKA <bf/4.0-current/ <item><bf/HEAD/ 即 <bf/-current/ 即 <bf/4.0-current/
</itemize> </itemize>
<p><bf/HEAD/ is not an actual branch tag, like the other two, it's <p>如同其他兩個,<bf/HEAD/ 並不是真正的 branch tag它只是一個符號
simply a symbolic constant for 常數,指向 <em/"current尚未分支的發展中版本"/ ,簡記為
<em/"the current, non-branched development stream"/ which we simply <bf/-current/。
refer to as <bf/-current/.
<p>Right now, <bf/-current/ is the 4.0 development stream and the <p>以現在來說,<bf/-current/ 朝向 4.0 發展,而 <bf/3.0-stable/ 這
<bf/3.0-stable/ branch, <bf/RELENG_3/, forked off from 個分支,也就是 <bf/RELENG_3/,在 1999 年 1 月從 <bf/-current/ 分出
<bf/-current/ in Jan 1999. 來。
<p>The <bf/2.2-stable/ branch, <bf/RELENG_2_2/, departed -current in <p><bf/2.2-stable/ 這個分支,也就是 <bf/RELENG_2_2/,是在 1996 年
November 1996. 11 月從 -current 分出來。
<p>The <bf/2.1-stable/ branch, <bf/RELENG_2_1_0/, departed -current in <p><bf/2.1-stable/ 這個分支,也就是 <bf/RELENG_2_1_0/,則是在
September of 1994. This branch has been fully retired. 1994 年 9 月從 -current 分支出來,這個分支已經完全退休了。
<sect1> <sect1>
<heading> <heading>
How do I make my own custom release?<label id="custrel"> 我要怎麼作出自己的 release<label id="custrel">
</heading> </heading>
<p>To make a release you need to do three things: First, you need to <p>做 release 包括下面這三個步驟:首先,做出有 <htmlurl
be running a kernel with the <htmlurl url="http://www.freebsd.org/cgi/man.cgi?vn" name="vn"> 這個驅動程
url="http://www.freebsd.org/cgi/man.cgi?vn" name="vn"> driver configured 式的可用 kernel。把下面這一行加到 kernel 設定檔,然後做出新的
in. Add this to your kernel config file and build a new kernel: kernel 重新開機:
<verb> <verb>
pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device vn #Vnode driver (turns a file into a device)
</verb> </verb>
<p>Second, you have to have the whole CVS repository at hand. <p>接著,你手上要有整個 CVS repository。可以參考 <url
To get this you can use <url url="../../handbook/cvsup.html" name="CVSUP"> url="../handbook/cvsup.html" name="CVSUP"> 這篇文章,但在 supfile
but in your supfile set the release name to cvs and remove any tag or 中把 release 名稱設成 cvs再刪掉所有 tag 或 date 的欄位,如下:
date fields:
<verb> <verb>
*default prefix=/home/ncvs *default prefix=/home/ncvs
@ -72,12 +68,11 @@
doc-all doc-all
</verb> </verb>
<p>Then run <tt/cvsup -g supfile/ to suck all the good bits onto your <p>然後執行 <tt/cvsup -g supfile/ 把所有東西都抓下來...
box...
<p>Finally, you need a chunk of empty space to build into. Let's <p>最後,硬碟要有相當大的空間來做 release。假設你想把它放在
say it's in <tt>/some/big/filesystem</tt>, and from the example <tt>/some/big/filesystem</tt> 這裡,上面這個例子也把 CVS
above you've got the CVS repository in <tt>/home/ncvs</tt>: repository 放在 <tt>/home/ncvs</tt> 了,接著:
<verb> <verb>
setenv CVSROOT /home/ncvs # or export CVSROOT=/home/ncvs setenv CVSROOT /home/ncvs # or export CVSROOT=/home/ncvs
@ -85,70 +80,59 @@
make release BUILDNAME=3.0-MY-SNAP CHROOTDIR=/some/big/filesystem/release make release BUILDNAME=3.0-MY-SNAP CHROOTDIR=/some/big/filesystem/release
</verb> </verb>
<p>An entire release will be built in <p>整個 release 會做在 <tt>/some/big/filesystem/release</tt>。結束
<tt>/some/big/filesystem/release</tt> and you will have a full FTP-type 時 <tt>/some/big/filesystem/release/R/ftp</tt> 這個目錄可以直接用
installation in <tt>/some/big/filesystem/release/R/ftp</tt> when you're 來做為 FTP 安裝方式的來源。如果想做出 -current 以外分支的 SNAP
done. If you want to build your SNAP along some other branch than 在上面 make release 這一行加 <tt/RELEASETAG=SOMETAG/。舉例來說,
-current, you can also add <tt/RELEASETAG=SOMETAG/ to <tt/RELEASETAG=RELENG_2_2/ 這個參數會做個即時的 2.2-STABLE snapshot。
the make release command line above, e.g. <tt/RELEASETAG=RELENG_2_2/
would build an up-to-the- minute 2.2-STABLE snapshot.
<sect1> <sect1>
<heading>How do I create customized installation disks?</heading> <heading>怎樣才能做出自己用的安裝磁片?</heading>
<p>The entire process of creating installation disks and source and <p>建立安裝磁片、還有做出 source/binary archive都是由
binary archives is automated by various targets in <tt>/usr/src/release/Makefile</tt> 裡面的各種 target 自動產生,這
<tt>/usr/src/release/Makefile</tt>. The information there should 個檔案裡的資訊應該足以開始。但是這個過程牽涉到 make world所以會
be enough to get you started. However, it should be said that this 用到相當多的時間和硬碟空間。
involves doing a ``make world'' and will therefore take up a lot of
time and disk space.
<sect1> <sect1>
<heading>``make world'' clobbers my existing installed binaries.</heading> <heading>``make world'' 把原來裝的 binary 檔都換掉了。</heading>
<p>Yes, this is the general idea; as its name might suggest, <p>沒錯,就是這樣子。如名字所示,``make world'' 會重新編譯系統內建
``make world'' rebuilds every system binary from scratch, so you can be 的每個 binary 檔,這樣在結束時就可確定有個一致且乾淨的環境(所以要
certain of having a clean and consistent environment at the end (which 花上好一段時間)。
is why it takes so long).
<p>If the environment variable <tt/DESTDIR/ is defined while running <p>在執行 ``<tt/make world/'' 或 ``<tt/make install/'' 時,如果有
``<tt/make world/'' or ``<tt/make install/'', the newly-created 設 <tt/DESTDIR/ 這個環境變數,新產生的 binary 將會裝在
binaries will be deposited in a directory tree identical to the <tt>&dollar;&lcub;DESTDIR&rcub;</tt> 下的同樣目錄樹中。但在某些修
installed one, rooted at <tt>&dollar;&lcub;DESTDIR&rcub;</tt>. 改 shared library 和重建 binary 的無特定情況下,這樣做可能會使
Some random combination of shared libraries modifications and ``<tt/make world/'' 失敗。
program rebuilds can cause this to fail in ``<tt/make world/'',
however.
<sect1> <sect1>
<heading> <heading>
When my system boots, it says ``(bus speed defaulted)''. 在系統開機時,出現 ``(bus speed defaulted)''。
</heading> </heading>
<p>The Adaptec 1542 SCSI host adapters allow the user to configure <p>Adaptec 1542 SCSI 卡允許使用者用軟體調整匯流排的存取速度。早
their bus access speed in software. Previous versions of the 期的 1542 驅動程式試圖將它設成可用的最快速度,但後來發現在一些
1542 driver tried to determine the fastest usable speed and set 機器上不能用,所以現在要在 kernel 設定中加 ``<tt/TUNE&lowbar;1542/''
the adapter to that. We found that this breaks some users' 這個選項來啟動這個功能。在支援的機器上用這個選項會使硬碟存取更
systems, so you now have to define the ``<tt/TUNE&lowbar;1542/'' kernel 快,但在不支援的機器上有可能會毀掉資料。
configuration option in order to have this take place. Using it
on those systems where it works may make your disks run faster,
but on those systems where it doesn't, your data could be
corrupted.
<sect1> <sect1>
<heading> <heading>
Can I follow current with limited Internet access?<label id="ctm"> 我的網路連線不快,那可以跟著 current 的發展嗎?<label id="ctm">
</heading> </heading>
<p>Yes, you can do this <tt /without/ downloading the whole source tree <p>可以,藉著 <url url="../handbook/ctm.html" name="CTM"> 就
by using the <url url="../../handbook/ctm.html" name="CTM facility."> 可以不用下傳所有的原始碼目錄樹。
<sect1> <sect1>
<heading>How did you split the distribution into 240k files?</heading> <heading>你是怎麼把發行版本中的檔案切成一個個 240k 的小檔案?</heading>
<p>Newer BSD based systems have a ``<tt/-b/'' option to split that <p>在以 BSD 為主的較新系統中split 有個 ``<tt/-b/'' 選項,是用來
allows them to split files on arbitrary byte boundaries. 把檔案以任意數目 byte 切開。
<p>Here is an example from <tt>/usr/src/Makefile</tt>. <p>這裡是 <tt>/usr/src/Makefile</tt> 中的一個例子:
<verb> <verb>
bin-tarball: bin-tarball:
@ -160,166 +144,130 @@
</verb> </verb>
<sect1> <sect1>
<heading>I've written a kernel extension, who do I send it to?</heading> <heading>我在 kernel 裡加了些新功能,要把它寄給誰?</heading>
<p>Please take a look at <url url="../../handbook/contrib.html" <p>請看一下 <url url="../handbook/contrib.html"
name="The Handbook entry on how to submit code."> name="Handbook 中加入程式碼的部份">。
<p>And thanks for the thought! <p>同時也感謝你的費心!
<sect1> <sect1>
<heading>How are Plug N Play ISA cards detected and initialized?</heading> <heading>ISA 的 Plug N Play 卡是怎麼偵測和初始化的?</heading>
<p>By: <url url="mailto:uhclem@nemesis.lonestar.org" <p> <url url="mailto:uhclem@nemesis.lonestar.org"
name="Frank Durda IV"> name="Frank Durda IV"> 所寫:
<p>In a nutshell, there a few I/O ports that all of the PnP boards <p>簡單的說,當主機發出是否有 PnP 卡的詢問訊號時,所有的 PnP
respond to when the host asks if anyone is out there. So when 會在幾個固定的 I/O port 作回應。所以當偵測 PnP 的程式開始時,它
the PnP probe routine starts, he asks if there are any PnP boards 會先問有沒有 PnP 卡在,接著所有 PnP 卡會在它所讀的 port 以自己
present, and all the PnP boards respond with their model &num; to 的型號 &num; 作回答,這樣偵測程式就會得到一個 wired-OR ``yes''
a I/O read of the same port, so the probe routine gets a wired-OR 的數字,其中至少會有一個 bit 是打開的。然後偵測程式會要求型號
``yes'' to that question. At least one bit will be on in that (由 Microsoft/Intel指定)小於 X 的卡``離線'',再去看是否還有卡回
reply. Then the probe code is able to cause boards with board 答同樣的詢問,如果得到 ``<tt/0/'',就表示沒有型號大於 X 的卡。
model IDs (assigned by Microsoft/Intel) lower than X to go 現在程式會問是否有型號小於 X 的卡,如果有的話,程式再要型號大於
``off-line''. It then looks to see if any boards are still X-(limit/4) 的卡離線,然後重覆上面的動作。用這種類似 binary
responding to the query. If the answer was ``<tt/0/'', then search 的方法,在某範圍內找個幾次後,偵測程式最後會在機器中區分
there are no boards with IDs above X. Now probe asks if there 出所有的 PnP 卡,搜尋次數也遠低於一個個找的 2^64 次。
are any boards below ``X''. If so, probe knows there are boards
with a model numbers below X. Probe then asks for boards greater
than X-(limit/4) to go off-line. If repeats the query. By
repeating this semi-binary search of IDs-in-range enough times,
the probing code will eventually identify all PnP boards present
in a given machine with a number of iterations that is much lower
than what 2^64 would take.
<p>The IDs are two 32-bit fields (hence 2&circ;64) + 8 bit checksum. <p>一張卡的 ID 由兩個 32-bit(所以上面是 2&circ;64) + 8bit 偵錯
The first 32 bits are a vendor identifier. They never come out 碼組成,第一個 32 bits 是用來區分各家廠商的。這些廠商沒有出來澄
and say it, but it appears to be assumed that different types of 清過,但看來應假設同一家出的不同種類的卡的廠商 ID 有可能不同。
boards from the same vendor could have different 32-bit vendor 用 32 bits 只來表示不同廠商的想法實在有點過頭了。
ids. The idea of needing 32 bits just for unique manufacturers
is a bit excessive.
<p>The lower 32 bits are a serial &num;, ethernet address, something <p>第二個 32 bits 則是型號 &num、乙太網路位址、或一些使這張卡獨
that makes this one board unique. The vendor must never produce 特的資料。除非第一個 32 bits 不同,否則廠商不可能作出第二個 32
a second board that has the same lower 32 bits unless the upper bit 相同的兩張卡。所以在一台機器中可以有同樣的好幾張卡,然而他們
32 bits are also different. So you can have multiple boards of 整個 64 bits 還是會都不一樣。
the same type in the machine and the full 64 bits will still be
unique.
<p>The 32 bit groups can never be all zero. This allows the <p>這兩個 32 bit 永遠都不可能為零,這使得最開始 binary search 中
wired-OR to show non-zero bits during the initial binary search. 的 wired-OR 會得到一個非零數字。
<p>Once the system has identified all the board IDs present, it will <p>一旦系統區分出所有卡的 ID接著會經由同樣的 port 一個個重新啟
reactivate each board, one at a time (via the same I/O ports), 動每張卡,接著找出已知介面卡所需的資源、有那些可以選的 interrupt
and find out what resources the given board needs, what interrupt 等等。所有卡都會被掃描一次,來收集這些資料。
choices are available, etc. A scan is made over all the boards
to collect this information.
<p>This info is then combined with info from any ECU files on the <p>這些資訊接著和硬碟上的 ECU 檔案、或 MLB BIOS 裡的資料結合在一
hard disk or wired into the MLB BIOS. The ECU and BIOS PnP 起,通常是綜合 ECU 和 MLB 裡的 BIOS PnP 資料,這些週邊並不支援真
support for hardware on the MLB is usually synthetic, and the 正的 PnP然而偵測程式在檢查 BIOS 和 ECU 資料後,它可以避免 PnP
peripherals don't really do genuine PnP. However by examining 週邊和那些偵測不到的相衝突。
the BIOS info plus the ECU info, the probe routines can cause the
devices that are PnP to avoid those devices the probe code cannot
relocate.
<p>Then the PnP devices are visited once more and given their I/O, <p>接著再度拜訪這些 PnP 週邊,這次會把可用的 I/O、DMA、IRQ 和記
DMA, IRQ and Memory-map address assignments. The devices will 憶體映射的位址都指定給它們。這些週邊就會出現在所指定的地方,直到
then appear at those locations and remain there until the next 下一次重新開機為止,不過也沒有人說不能把它們隨時移來移去。
reboot, although there is nothing that says you can't move them
around whenever you want.
<p>There is a lot of oversimplification above, but you should get <p>上面有相當多的簡化,但你應該已經了解大致的過程。
the general idea.
<p>Microsoft took over some of the primary printer status ports to <p>Microsoft 把表示印表機狀態的幾個主要 port 拿來作 PnP他們的
do PnP, on the logic that no boards decoded those addresses for 邏輯是沒有一張卡會在這些地方解碼作相反的 I/O cycles。但是我找到
the opposing I/O cycles. I found a genuine IBM printer board 一款早期仍在評估 PnP 提案時的 IBM 原廠 printer board它的確去解
that did decode writes of the status port during the early PnP 對這些狀態 port 的寫入資料,但是 MS ``說了就算''。所以它們的確有
proposal review period, but MS said ``tough''. So they do a 對印表機狀態 port 寫入,還有讀取該位址 + <tt/0x800/、和另一個在
write to the printer status port for setting addresses, plus that <tt/0x200/ 及 <tt/0x3ff/ 之間的 port。
use that address + <tt/0x800/, and a third I/O port for reading
that can be located anywhere between <tt/0x200/ and <tt/0x3ff/.
<sect1> <sect1>
<heading>Does FreeBSD support architectures other than the x86?</heading> <heading>FreeBSD 是否有支援 x86 以外的機器架構?</heading>
<p>Several groups of people have expressed interest in working on <p>有幾群人士已經表示對發展多平台 FreeBSD 的興趣,其中
multi-architecture ports for FreeBSD and the FreeBSD/AXP (ALPHA) FreeBSD/AXP (ALPHA) 即是其中相當成功的例子,可以在 <url
port is one such effort which has been quite successful, now
available in 3.0 SNAPshot release form at <url
url="ftp://ftp.freebsd.org/pub/FreeBSD/alpha/" url="ftp://ftp.freebsd.org/pub/FreeBSD/alpha/"
name="ftp://ftp.freebsd.org/pub/FreeBSD/alpha">. The ALPHA name="ftp://ftp.freebsd.org/pub/FreeBSD/alpha"> 這裡取得它的
port currently runs on a growing number of ALPHA machine 3.0 SNAPshot 版本。ALPHA 版的 FreeBSD 在越來越多的 ALPHA 機器上
types, among them the AlphaStation, AXPpci, PC164, Miata and Multia 使用,其中包括了 AlphaStation、AXPpci、PC164、Miata 和 Multia
models. This port is not yet considered a full release and won't be 這幾種。要等到系統安裝工具完全、能用光碟安裝、以及有足夠能用的
until a full compliment of system installation tools and a distribution port/package 之後,我們才打算把它當作完整的版本,所以現在應該把
on CDROM installation media is available, including a reasonable FreeBSD/AXP 當作 BETA 品質的軟體。若要相關狀況的消息,請加入
number of working ports and packages.
FreeBSD/AXP should be considered BETA quality software at this
time. For status information, please join the
<tt>&lt;freebsd-alpha@FreeBSD.ORG&gt;</tt><ref id="mailing" <tt>&lt;freebsd-alpha@FreeBSD.ORG&gt;</tt><ref id="mailing"
name="mailing list">. name="mailing list">.
Interest has also been expressed in a port of FreeBSD to 也有人表示過將 FreeBSD SPARC 版本的興趣,如果你想參加這個計畫,
the SPARC architecture, join the <tt>&lt;freebsd-sparc@FreeBSD.ORG&gt; 請加入 <tt>&lt;freebsd-sparc@FreeBSD.ORG&gt;
</tt><ref id="mailing" name="mailing list"> if you are interested </tt><ref id="mailing" name="mailing list">。如果想要知道關於
in joining that project. For general discussion on new architectures, 新平台的討論,請加入 <tt>&lt;freebsd-platforms@FreeBSD.ORG&gt;</tt>
join the <tt>&lt;freebsd-platforms@FreeBSD.ORG&gt;</tt> <ref id="mailing" name="mailing list">。
<ref id="mailing" name="mailing list">.
<sect1> <sect1>
<heading>I need a major number for a device driver I've written.</heading> <heading>我剛剛寫了某個設備的驅動程式,能不能給它一個 major number
</heading>
<p>This depends on whether or not you plan on making the driver
publicly available. If you do, then please send us a copy of the
driver source code, plus the appropriate modifications to
<tt>files.i386</tt>, a sample configuration file entry, and the
appropriate <htmlurl url="http://www.freebsd.org/cgi/man.cgi?MAKEDEV"
name="MAKEDEV"> code to create any special files your device uses. If
you do not, or are unable to because of licensing restrictions, then
character major number 32 and block major number 8 have been reserved
specifically for this purpose; please use them. In any case, we'd
appreciate hearing about your driver on
<tt>&lt;freebsd-hackers@FreeBSD.ORG&gt;</tt>.
<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> <sect1>
<heading>Alternative layout policies for directories</heading> <heading>關於放置目錄和檔案 inode 作法上的相異</heading>
<p> <p>在回答有關目錄放置方式不同的問題上,我在 1983 年寫好目前的作法
In answer to the question of alternative layout policies for 後就沒有再改變過,這種方式是針對原先的 FFS 檔案系統,後來也沒
directories, the scheme that is currently in use is unchanged 有對它作任何更動。它在避免 cylinder group 被填滿這方面做得相當
from what I wrote in 1983. I wrote that policy for the original 成功,但是就像有些人已經注意到,它和 `find' 就配合得不大好。大
fast filesystem, and never revisited it. It works well at keeping 部份的檔案系統是由那些用 depth first search(aka ftw) 產生的
cylinder groups from filling up. As several of you have noted, archive 製造出來,解出來的目錄 inode 會橫跨好幾個 cylinder
it works poorly for find. Most filesystems are created from group如果以後要做 depth first search 的話,這是最糟糕的情況之
archives that were created by a depth first search (aka ftw). 一。如果我們知道總共會產生多少目錄的話,解法是在做任何存取/寫
These directories end up being striped across the cylinder groups 入動作之前,在每個 cylinder group 上先造出(所有目錄數/cylinder
thus creating a worst possible senario for future depth first greoup 的數目)這麼多的目錄。很明顯的,我們必須要有根據地去猜這
searches. If one knew the total number of directories to be 個數字,就算一個像 10 的很小固定數目也會使效率以級數成長。區分
created, the solution would be to create (total / fs_ncg) per restore (即解開上述的 archive) 和一般檔案操作的方法可以是(現在
cylinder group before moving on. Obviously, one would have to 用的演算法可能要更敏感):如果一些目錄(最多 10 個)都在 10 秒內產
create some heuristic to guess at this number. Even using a 生的話,那麼就把這些目錄聚集在同一個 cylinder group。不管怎樣
small fixed number like say 10 would make an order of magnitude 我的經驗指出這是一個已經充份實驗過的部份。</p>
improvement. To differentiate restores from normal operation
(when the current algorithm is probably more sensible), you
could use the clustering of up to 10 if they were all done
within a ten second window. Anyway, my conclusion is that this
is an area ripe for experimentation.</p>
<p>Kirk McKusick, September 1998</p> <p>Kirk McKusick, September 1998</p>
<sect1> <sect1>
<heading>Making the most of a kernel panic</heading> <heading>如何從 kernel panic 得到最多資訊?</heading>
<p> <p>
<em>[This section was extracted from a mail written by <url <em>[這節是從 <url url="mailto:wpaul@FreeBSD.ORG" name="Bill Paul">
url="mailto:wpaul@FreeBSD.ORG" name="Bill Paul"> on the 在 freebsd-current <ref id="mailing" name="mailing list"> 上發表
freebsd-current <ref id="mailing" name="mailing list"> by <url 的信中節錄,<url url="mailto:des@FreeBSD.ORG"
url="mailto:des@FreeBSD.ORG" name="Dag-Erling Co&iuml;dan name="Dag-Erling Co&iuml;dan Sm&oslash;rgrav"> 修正了打字錯誤、再
Sm&oslash;rgrav">, who fixed a few typos and added the bracketed 加上括弧裡的注解。]</em>
comments]</em>
<p> <p>
<verb> <verb>
@ -331,8 +279,7 @@ Cc: current@FreeBSD.ORG
</verb> </verb>
<p> <p>
<em>[&lt;ben@rosengart.com&gt; posted the following panic <em>[&lt;ben@rosengart.com&gt; 發表了下面的 panic 訊息]</em>
message]</em>
<verb> <verb>
> Fatal trap 12: page fault while in kernel mode > Fatal trap 12: page fault while in kernel mode
> fault virtual address = 0x40 > fault virtual address = 0x40
@ -350,112 +297,93 @@ Cc: current@FreeBSD.ORG
> panic: page fault > panic: page fault
</verb> </verb>
<p> [When] you see a message like this, it's not enough to just <p>當你看到像這樣的訊息時,只把它拷一份送上來是不夠的。我在上
reproduce it and send it in. The instruction pointer value that 面特地標明的 instruction pointer 值相當重要,不幸的是它會因設
I highlighted up there is important; unfortunately, it's also 定而不同。換句話說,這個值會跟你用的 kernel image 檔而變動。如
configuration dependent. In other words, the value varies 果是用某個 snapshot 版本的 GENERIC kernel也許其他人可以追蹤
depending on the exact kernel image that you're using. If you're 到出問題的函式,但如果你是用自訂的 kernel那麼只有<em/你/才能
using a GENERIC kernel image from one of the snapshots, then 告訴我們問題出在那裡。
it's possible for somebody else to track down the offending
function, but if you're running a custom kernel then only
<em/you/ can tell us where the fault occured.
<p> What you should do is this: <p>要做的事包括這些:
<itemize> <itemize>
<item>Write down the instruction pointer value. Note that the <item>把 instruction pointer 的值記下來。注意在前面的 <tt/0x8:/
<tt/0x8:/ part at the begining is not significant in this case: 在這個情況中並不重要,我們要的是 <tt/0xf0xxxxxx/。
it's the <tt/0xf0xxxxxx/ part that we want.
<item>When the system reboots, do the following: <item>當系統重新開機後,執行這道命令:
<verb> <verb>
% nm /kernel.that.caused.the.panic | grep f0xxxxxx % nm /(造成 panic 的 kernel 檔案) | grep f0xxxxxx
</verb> </verb>
where <tt/f0xxxxxx/ is the instruction pointer value. The 其中 <tt/f0xxxxxx/ 就是記下來的 instruction pointer 值。有可能
odds are you will not get an exact match since the symbols 不會剛好找到完整的這個字串,這是因為 kernel symbol table 裡的各
in the kernel symbol table are for the entry points of 個 symbol 只是函式的進入點,但 instruction pointer 所指的位址有
functions and the instruction pointer address will be 可能是在函式內的某一處,而不一定在開頭。所以如果找不到整個字串,
somewhere inside a function, not at the start. If you don't 那麼把 instruction pointer 值的最後一個數字拿掉,再試一次:
get an exact match, omit the last digit from the instruction
pointer value and try again, i.e.:
<verb> <verb>
% nm /kernel.that.caused.the.panic | grep f0xxxxx % nm /kernel.that.caused.the.panic | grep f0xxxxx
</verb> </verb>
If that doesn't yield any results, chop off another digit. 如果這樣也找不到,那就把另一個數字去掉再找,一直重複到找到為止,
Repeat until you get some sort of output. The result will be 結果是一串可能造成 panic 的函式列表。這樣比直接找到出問題的函式
a possible list of functions which caused the panic. This is 來得差,但至少好過什麼都沒有。
a less than exact mechanism for tracking down the point of
failure, but it's better than nothing.
</itemize> </itemize>
<p> I see people constantly show panic messages like this but <p>我常常看到人們顯示一大片 panic 訊息,但很少看到有人花一點時間
rarely do I see someone take the time to match up the 把 instruction pointer 和 kernel symbol table 中的函式比較一下。
instruction pointer with a function in the kernel symbol table.
<p> The best way to track down the cause of a panic is by <p>要追蹤出造成 panic 原因的最好方法是先做出 crash dump然後用
capturing a crash dump, then using <tt/gdb(1)/ to to a stack <tt/gdb(1)/ 在上面做 stack trace。當然這要靠 -current 中的
trace on the crash dump. Of course, this depends on <tt/gdb(1)/ <tt/gdb(1)/ 能運作正常,然而我無法保證這一點。(記得有人說 ELF 的
in -current working correctly, which I can't guarantee (I recall <tt/gdb(1)/ 在 kernel 的 crash dump 上不能正常操作,在 3.0 脫離
somebody saying that the new ELF-ized <tt/gdb(1)/ didn't handle BETA 階段時最好有人先檢查這方面的狀況,免得很多人在收到 3.0 光碟
kernel crash dumps correctly: somebody should check this before 後脹紅了臉。)
3.0 goes out of beta or there'll be a lot of red faces after the
CDs ship).
<p> <p>
In any case, the method I normally use is this: 不管是那一種,我通常是用這個方法:
<itemize> <itemize>
<item>Set up a kernel config file, optionally adding 'options DDB' if you <item>寫好 kernel 設定檔。如果你需要用 kernel debugger在設定
think you need the kernel debugger for something. (I use this mainly 檔中加上 `options DDB' 這個選項。(當我懷疑有出現無窮迴圈時,通
for setting beakpoints if I suspect an infinite loop condition of 常會用這個來設定中斷點。)
some kind.) <item>用 <tt/config -g KERNELCONFIG/ 做出用來編譯的目錄
<item>Use <tt/config -g KERNELCONFIG/ to set up the build directory.
<item><tt>cd /sys/compile/KERNELCONFIG; make</tt> <item><tt>cd /sys/compile/KERNELCONFIG; make</tt>
<item>Wait for kernel to finish compiling. <item>等 kernel 編譯出來
<item><tt/cp kernel kernel.debug/ <item><tt/cp kernel kernel.debug/
<item><tt/strip -d kernel/ <item><tt/strip -d kernel/
<item><tt/mv /kernel /kernel.orig/ <item><tt/mv /kernel /kernel.orig/
<item><tt>cp kernel /</tt> <item><tt>cp kernel /</tt>
<item>reboot <item>重新開機
</itemize> </itemize>
<p> <em>[Note: Now that FreeBSD 3.x kernels are Elf by default, <p> <em>[注意:現在 FreeBSD 3.x kernel 內定是 ELF 格式,所以應該
you should use <tt/strip -g/ instead of <tt/strip -d/. If for some 用 <tt/strip -g/ 而不是 <tt/strip -d/。如果你的 kernel 因某種原
reason your kernel is still a.out, use <tt/strip -aout -d/.]</em> 因仍是 a.out 格式的話,則用 <tt/strip -aout -d/。]</em>
<p> Note that YOU DO <em/NOT/ WANT TO ACTUALLY BOOT THE KERNEL <p>注意你<em/不會/真的用包括所有 debug symbol 的 kernel 來開機,
WITH ALL THE DEBUG SYMBOLS IN IT. A kernel compiled with <tt/-g/ 用 <tt/-g/ 編譯出來的 kernel 大小很容易就超過 10MB。不需要用這麼
can easily be close to 10MB in size. You don't have to actually 大的 kernel 開機,晚一點 <tt/gdb(1)/ 才會需要它(<tt/gdb(1)/ 會用
boot this massive image: you only need it later for <tt/gdb(1)/ 到裡面的 symbol table)。所以我們才會把完整的 kernel 複製一份,接
(<tt/gdb(1)/ wants the symbol table). Instead, you want to keep 著用 <tt/strip -d/ 刪掉 debug symbol做出第二個 kernel這個才真
a copy of the full image and create a second image with the 正拿來開機。
debug symbols stripped out using <tt/strip -d/. It is this
second stripped image that you want to boot.
<p> To make sure you capture a crash dump, you need edit <p>要確定能抓到 crash dump先編輯 <tt>/etc/rc.conf</tt>,將
<tt>/etc/rc.conf</tt> and set <tt/dumpdev/ to point to your swap <tt/dumpdev/ 指到 swap 分割區。這樣 <tt/rc(8)/ 會用 <tt/dumpon(8)/
partition. This will cause the <tt/rc(8)/ scripts to use the 來啟動 crash dump你也可以手動用 <tt/dumpon(8)/。在 panic 之後,
<tt/dumpon(8)/ command to enable crash dumps. You can also run crash dump 可以用 <tt/savecore(8)/ 存起來;如果 <tt>/etc/rc.conf</tt>
<tt/dumpon(8)/ manually. After a panic, the crash dump can be 裡有設 <tt/dumpdev/,那麼重新開機後 <tt/rc(8)/ 會自動執行
recovered using <tt/savecore(8)/; if <tt/dumpdev/ is set in <tt/savecore(8)/ 把 crash dump 存在 <tt>/var/crash</tt>。
<tt>/etc/rc.conf</tt>, the <tt/rc(8)/ scripts will run
<tt/savecore(8)/ automatically and put the crash dump in
<tt>/var/crash</tt>.
<p> NOTE: FreeBSD crash dumps are usually the same size as the <p>注意FreeBSD 的 crash dump 通常和機器裡的實際記憶體一樣大,
physical RAM size of your machine. That is, if you have 64MB of 就像如果有 64MB 記憶體crash dump 大小就是 64MB。所以要確定
RAM, you will get a 64MB crash dump. Therefore you must make sure <tt>/var/crash</tt> 下有足夠的空間,或是可以手動執行 <tt/savecore(8)/
there's enough space in <tt>/var/crash</tt> to hold the dump. 把 crash dump 放到另一個空間較夠的目錄下。另一種也許可以限制 crash
Alternatively, you run <tt/savecore(8)/ manually and have it dump 的方法,是在 kernel 設定檔中用 <tt/options MAXMEM=(foo)/
recover the crash dump to another directory where you have more 將 kernel 可用的記憶體限制在合理的大小。舉例來說,如果你有 128MB
room. It's possible to limit the size of the crash dump by using 的記憶體,但是可以限制 kernel 只能用 16MB 的記憶體,這樣 crash
<tt/options MAXMEM=(foo)/ to set the amount of memory the kernel dump 就是 16MB 而不是 128MB 了。
will use to something a little more sensible. For example, if
you have 128MB of RAM, you can limit the kernel's memory usage
to 16MB so that your crash dump size will be 16MB instead of
128MB.
<p> Once you have recovered the crash dump, you can get a stack <p>一旦發現有了 crash dump就可以用 <tt/gdb(1)/ 來做 stack trace
trace with <tt/gdb(1)/ as follows: ,如下所示:
<p> <p>
<verb> <verb>
@ -463,30 +391,94 @@ Cc: current@FreeBSD.ORG
(gdb) where (gdb) where
</verb> </verb>
<p> Note that there may be several screens worth of information; <p>要注意可能會出現好幾個螢幕的可用資訊,你可以用 <tt/script(1)/
ideally you should use <tt/script(1)/ to capture all of them. 把所有輸出都存起來。用包括所有 debug symbol 的 kernel 來除錯,
Using the unstripped kernel image with all the debug symbols 這樣應該可以直接顯示 panic 是發生在那一行。通常是由下往上讀 stack
should show the exact line of kernel source code where the panic strace這樣才能一個個追蹤出有那些動作引到 crash。也可以用
occured. Usually you have to read the stack trace from the <tt/gdb(1)/ 把各種變數或結構的內容印出來,以檢查系統 crash 時的
bottom up in order to trace the exact sequence of events that 實際狀態。
lead to the crash. You can also use <tt/gdb(1)/ to print out the
contents of various variables or structures in order to examine
the system state at the time of the crash.
<p> Now, if you're really insane and have a second computer, you <p>好啦,如果你有第二台電腦而且有夠瘋狂,可以將 <tt/gdb(1)/ 設定
can also configure <tt/gdb(1)/ to do remote debugging such that 成遠端除錯。這樣你可以在一台機器中用 <tt/gdb(1)/ 去除錯另一台裡的
you can use <tt/gdb(1)/ on one system to debug the kernel on kernel可以執行的包括設定中斷點、在 kernel 原始碼中一步步執行等
another system, including setting breakpoints, single-stepping 等,就像在一般使用者程式上除錯一樣。由於沒有什麼機會為除錯而設置
through the kernel code, just like you can do with a normal 兩台並鄰電腦,所以我還沒有這樣玩過。
user-mode program. I haven't played with this yet as I don't
often have the chance to set up two machines side by side for
debugging purposes.
<p> <em>[Bill adds: "I forgot to mention one thing: if you have <p><em>[Bill 附注:我忘了提到一點:如果你有啟動 DDB 而 kernel 也
DDB enabled and the kernel drops into the debugger, you can 已經進入除錯器,可以在 DDB 命令列下打 `panic',強迫產生 panic(還
force a panic (and a crash dump) just by typing 'panic' at the 有 crash dump)。也有可能在 panic 階段時再進入除錯器,如果這樣的話
ddb prompt. It may stop in the debugger again during the panic ,輸入 `continue',接著它就會完成 crash dump。 -ed]</em>
phase. If it does, type 'continue' and it will finish the 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/ 設成這個值,接著將 section 列表最前面的
location counter 設成相同的值(譯注:在
<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 和做出新的 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><em>[<url url="mailto:dg@freebsd.org" name="David Greenman">
加上這一段:我認為 kernel 定址空間大小應該是 2 的乘冪,但不大確
定這一點。舊的啟動程式會動到 high order address bits記得它假設
至少有 256 MB。]</em>
</sect> </sect>

File diff suppressed because it is too large Load diff