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