昔は、OSをインストールしたら、まずはカーネル(kernel)のリコンフィグ(reconfiguration=再構築/または単にbuild=ビルド/カーネルをコンパイルしなおすこと)を行い、使用しているハードウェアにあったデバイスドライバを追加したり、OSの動きが軽快になるようにチューニングしたりする、というのが、まず最初にやるべき作業だったような気がします。しかし最近では、デバイスドライバもモジュール化されているし、/boot/loader.confや/etc/sysctl.confなどで様々なパラメータを調節できるようになっているため、カーネルを再構築する必要もありません。
私も、Solarisではカーネルの再構築ってやったことないですし(てゆーかできるの?)、Linuxでも、もう何年もやった記憶がありません。ただ、FreeBSDでは、なんとなく趣味というか、たいていカーネル再構築をやってます。
自分専用にカスタマイズしたカーネルを作って、自分だけのカーネルでパソコンを動かす、ってところに、なんとなく愛着がわいてくるような気がしませんか?
昔のパソコンは、今ほど処理速度が速くないので、カーネル再構築によって、「カーネルのぜい肉を落とす」ことで、けっこう効果があったと思います(OSの起動時間が短縮されるくらい、という話もある・・・)。
VMwareで、仮想マシンの中でFreeBSDで動かすときは、それなりにオーバーヘッドもあるわけだし、じゃあ、ぜい肉を落としてやったっていーんじゃないでしょうか。
● 参考
「FreeBSDハンドブック」の、「カスタムカーネルの構築とインストール」
http://www.jp.freebsd.org/www.FreeBSD.org/doc/ja_JP.eucJP/books/handbook/kernelconfig-building.html
■ カーネルのソースコードをFTPでダウンロード
私はいつもFTPでFreeBSDをインストールしているのですが、必要なもの最小限しかインストールしないので、カーネルのソースコードは、後から別途ダウンロードする必要があります。
FreeBSDのソースコードは、このあたりに置かれています。
ftp://ftp3.jp.freebsd.org/pub/FreeBSD/releases/i386/6.1-RELEASE/src/
ここにおかれているファイルは、tarとgzipで圧縮したあと、フロッピーディスクに入る程度のファイルサイズへ分割されたものです。カーネルのソースコードは、「ssys.??」というファイルが該当します。
FreeBSDで、ftpコマンドを使ってダウンロードする方法は、以下のとおり。
(ダウンロードしたファイルを置くディレクトリへ、あらかじめ移動しておくのが楽)
freebsd# cd /usr/src
freebsd# ftp ftp3.jp.freebsd.org
Trying 2001:e40:100:207::2...
ftp: connect to address 2001:e40:100:207::2: No route to host
Trying 210.188.213.230...
Connected to ring.sakura.ad.jp.
220 ProFTPD 1.3.0rc2 Server (ring.sakura.ad.jp) [::ffff:210.188.213.230]
Name (ftp3.jp.freebsd.org:nhh): ftp ←(ftpと入力)
331 Anonymous login ok, send your complete email address as your password.
Password: ←(メールアドレスをパスワード代わりに入力)
230-
##################################################
# Welcome to the RingServer FTP service. #
##################################################
Localtime [Thu Jun 8 22:13:23 2006 JST+0900]
Current [13] users / Max [100] users
230 Anonymous access granted, restrictions apply.
Remote system type is UNIX.
Using binary mode to transfer files.
(ディレクトリ移動・・・ところで、ここでTABキーを押してファイル名補完ができるので、びっくりしました)
ftp> cd /pub/FreeBSD/releases/i386/6.1-RELEASE/src
(バイナリモードでファイル転送するように指示)
ftp> bin
200 Type set to I
(ssys*にマッチするファイルをすべてダウンロード)
ftp> mget ssys*
mget ssys.aa [anpqy?]? a ←(aで、これ以降いちいち尋ねずにすべてYesと答えるようになる)
Prompting off for duration of mget.
(ダウンロードがはじまる)
229 Entering Extended Passive Mode (|||64410|)
150 Opening BINARY mode data connection for ssys.aa (1425408 bytes)
100% |*************************************| 1392 KB 886.28 KB/s 00:00 ETA
226 Transfer complete.
1425408 bytes received in 00:01 (873.16 KB/s)
229 Entering Extended Passive Mode (|||50087|)
150 Opening BINARY mode data connection for ssys.ab (1425408 bytes)
100% |*************************************| 1392 KB 0.97 MB/s 00:00 ETA
226 Transfer complete.
1425408 bytes received in 00:01 (985.12 KB/s)
(省略)
229 Entering Extended Passive Mode (|||51647|)
150 Opening BINARY mode data connection for ssys.inf (486 bytes)
100% |*************************************| 486 29.78 KB/s 00:00 ETA
226 Transfer complete.
486 bytes received in 00:00 (11.70 KB/s)
(ダウンロード完了)
ftp> bye
221 Goodbye.
(ダウンロードされたファイル)
freebsd# ls
ssys.aa ssys.ae ssys.ai ssys.am ssys.inf
ssys.ab ssys.af ssys.aj ssys.an
ssys.ac ssys.ag ssys.ak ssys.ao
ssys.ad ssys.ah ssys.al ssys.ap
■ ソースコードの展開
ssys.??にマッチするファイルをcatで連結して、tar+gzipの展開をします。
freebsd# cat ssys.?? | tar zxf -
展開されたファイルは、sysというサブディレクトリの中にあります。
freebsd# ls sys
Makefile ddb kern netkey posix4
alpha dev libkern netnatm powerpc
amd64 doc modules netncp rpc
arm fs net netsmb security
boot gdb net80211 nfs sparc64
bsm geom netatalk nfs4client sys
cam gnu netatm nfsclient tools
coda i386 netgraph nfsserver ufs
compat i4b netinet opencrypto vm
conf ia64 netinet6 pc98
contrib isa netipsec pccard
crypto isofs netipx pci
■ カーネルのコンフィギュレーションファイルを作成
ディレクトリ/usr/src/sys/i386/conf/にて、GENERICカーネルのコンフィギュレーションファイルを元に、カスタム・カーネル用のコンフィギュレーションファイルを作成します。
(ディレクトリ移動)
freebsd# cd /usr/src/sys/i386/conf/
(ちなみに、/sysというシンボリックリンクがあるので、cd /sys/i386/confとするのが粋なFreeBSDユーザーです)
(ファイルをコピーして)
freebsd# cp GENERIC VMware
(またまたちなみに、ここでのファイル名は、ホスト名をすべて大文字にしたものにするのが慣例と言われています・・・が、そんな慣例は、けっこう昔から破ってます)
(エディタでファイルを編集)
freebsd# vi VMware
いらないデバイスは、行頭に「#」マークをつけて、ガシガシと、コメントアウトしていきます。
ただし、必要なものまで消してしまうと、カーネルのコンパイルに失敗します。このへんは、経験と勘が必要かも。
私が先ほど作ったVMware用のカーネルのコンフィギュレーション・ファイルは、コメントアウトした行と、改行だけの行を除くと、こんな感じになりました。最後の2行は、VMwareでエミュレーションされるオーディオデバイス用のドライバです。
# grep -v '^#' VMware | sed -e '/^$/d'
machine i386
cpu I686_CPU
ident VMware
options SCHED_4BSD # 4BSD scheduler
options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
options MD_ROOT # MD is a potential root device
options NFSCLIENT # Network Filesystem Client
options NFSSERVER # Network Filesystem Server
options NFS_ROOT # NFS usable as /, requires NFSCLIENT
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
options GEOM_GPT # GUID Partition Tables.
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options COMPAT_FREEBSD4 # Compatible with FreeBSD4
options COMPAT_FREEBSD5 # Compatible with FreeBSD5
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extension
s
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
options AHC_REG_PRETTY_PRINT # Print register bitfields in debug
# output. Adds ~128k to driver.
options AHD_REG_PRETTY_PRINT # Print register bitfields in debug
# output. Adds ~215k to driver.
options ADAPTIVE_GIANT # Giant mutex is adaptive.
device apic # I/O APIC
device pci
device ata
device atadisk # ATA disk drives
device atapicd # ATAPI CDROM drives
options ATA_STATIC_ID # Static device numbering
device scbus # SCSI bus (required for SCSI)
device da # Direct Access (disks)
device atkbdc # AT keyboard controller
device atkbd # AT keyboard
device psm # PS/2 mouse
device vga # VGA video card driver
device sc
device agp # support several AGP chipsets
device pmtimer
device lnc # NE2100, NE32-VL Lance Ethernet cards
device loop # Network loopback
device random # Entropy device
device ether # Ethernet support
device tun # Packet tunnel.
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
device bpf # Berkeley packet filter
device uhci # UHCI PCI->USB interface
device usb # USB Bus (required)
device ugen # Generic
device umass # Disks/Mass storage - Requires scbus and da
device sound
device snd_es137x
「VMware.FreeBSD.CONFIG.txt」をダウンロード
■ カーネルのビルド
2通りの方法があって、「make buildkernel KERNCONF=ほげ」という新しいビルド方法があるのですが、ここでは、昔ながらの方法を紹介します。
まず、configコマンドを実行して、カーネルをコンパイルするための準備作業を行います。
freebsd# pwd
/usr/src/sys/i386/conf
freebsd# config VMware
Kernel build directory is ../compile/VMware
Don't forget to do ``make cleandepend; make depend''
これこれしろ、というメッセージにしたがって・・・
freebsd# cd ../compile/VMware/
昔はcleandependなんてものはなくて、つい最近増えたんですけど、素直に指示に従います。make dependも、それなりに時間がかかるので、「; make」も付け足して、一度に全部のコマンドを入力しちゃいます。
freebsd# make cleandepend; make depend; make
rm -f .depend
cd ../../../modules; MAKEOBJDIRPREFIX=/usr/src/sys/i386/compile/VMware/modules K
MODDIR=/boot/kernel MACHINE=i386 KERNBUILDDIR="/usr/src/sys/i386/compile/VMware"
make cleandepend
===> 3dfx (cleandepend)
(しばらく待つ・・・)
(途中ばっさりと省略)
awk -f /usr/src/sys/modules/zlib/../../conf/kmod_syms.awk zlib.kld export_syms
| xargs -J% objcopy % zlib.kld
ld -Bshareable -d -warn-common -o zlib.ko zlib.kld
objcopy --strip-debug zlib.ko
ファイルサイズを見てみます。
freebsd# ls -l kernel
-rwxr-xr-x 1 root wheel 3785839 Jun 8 23:19 kernel
ちなみに、オリジナルのカーネル(GENERICカーネル)の場合は・・・
freebsd# ls -l /boot/kernel/kernel
-r-xr-xr-x 1 root wheel 6639826 May 7 13:32 /boot/kernel/kernel
カスタム・カーネルは、だいぶ、ダイエットされたようですね。
■ 新しいカーネルをインストール
新しいカーネルは、「make install」で、/boot/kernel/以下へインストールすることができます。
freebsd# make install
thiskernel=`sysctl -n kern.bootfile` ; if [ ! "`dirname "$thiskernel"`" -ef /bo
ot/kernel ] ; then chflags -R noschg /boot/kernel ; rm -rf /boot/kernel ; els
e if [ -d /boot/kernel.old ] ; then chflags -R noschg /boot/kernel.old ; rm -
rf /boot/kernel.old ; fi ; mv /boot/kernel /boot/kernel.old ; sysctl kern.boo
tfile=/boot/kernel.old/"`basename "$thiskernel"`" ; fi
kern.bootfile: /boot/kernel/kernel -> /boot/kernel.old/kernel
mkdir -p /boot/kernel
install -p -m 555 -o root -g wheel kernel /boot/kernel
(省略)
===> zlib (install)
install -o root -g wheel -m 555 zlib.ko /boot/kernel
kldxref /boot/kernel
■ 新しいカーネルでブートする
リブートすれば、新しいカーネルで、FreeBSDが起動します。
freebsd# reboot
Connection to vmware closed by remote host.
Connection to vmware closed.
新しいカーネルで起動したあと、ログインし、「uname -a」コマンドを実行すると、カーネルをコンパイルしたときの日付などが表示されます。
freebsd# uname -a
FreeBSD freebsd.vmware.local 6.1-RELEASE FreeBSD 6.1-RELEASE #0: Thu Jun 8 23:19:32 JST 2006 nhh@freebsd.vmware.local:/usr/src/sys/i386/compile/VMware i386
■ 新しいカーネルで正常にブートできなかった場合
必要なデバイスドライバまで削除してしまったとか、コンフィギュレーション・ファイルに問題があった場合、正常にOSが動作しなくなる恐れがあります。
そういうときは、1つ前のカーネルでブートしなおします。
実は、「make install」で新しいカーネルをインストールしたとき、これまで使っていたカーネルは、/boot/kernel.oldというディレクトリに、そっくりそのまま残されています(1つ前のものしか残されないので、もっと残しておきたい場合は、自分で適当にディレクトリ名を変更して保存しておくこと)。
freebsd# ls -ld /boot/kernel*
drwxr-xr-x 2 root wheel 9216 Jun 8 23:56 /boot/kernel
drwxr-xr-x 2 root wheel 9216 May 13 09:13 /boot/kernel.old
シングルユーザーモードでもいいので、なんとかカーネルが起動して、rootでログインできた場合は、/boot/kernel.oldというディレクトリ名を、/boot/kernelに戻して、もう一度再起動すれば、1つ前のカーネルでブートさせることができます。
(シングルユーザーモードでブートしたときは、リードオンリーでマウントされているので、書き換え可能になるように、マウントしなおす)
# mount -u /
(古いカーネルを、復活させる)
# cd /boot
# mv kernel kernel.hoge
# mv kernel.old kernel
カーネルのブート途中にpanicしてしまうなど、最悪の場合は、ブートローダの段階で、ブートすべきカーネルを選択しなおします。
まず、FreeBSDをブートする最初の段階で、ブートローダーに入ります。デーモンくんやFreeBSDロゴが表示されているメニューが表示された場合は、「Escape to loader prompt」を選択します。
「OK」というプロンプトが表示されているので、以下のようにして、ブートすべきカーネルを切り替えます、
(すでにカーネル/boot/kernel/kernelがロードずみなので、アンロードする)
OK unload
(カーネルをロードする)
OK load /boot/kernel.old/kernel
(-s をつけて、シングルユーザーモードで起動)
OK boot -s
1つ前の/boot/kernel.old/kernelというカーネルでブートします。
ロードするカーネルのファイル名がわからなくなってしまった場合は、「ls /boot」のようなコマンドで、ファイル名の一覧を表示できます。
OK ls /boot
とにかく、カーネルが起動できたら、rootでログインして、上記の説明同様に、古いカーネルを復活させます。
# mount -u /
# cd /boot
# mv kernel kernel.hoge
# mv kernel.old kernel
■ 関連情報