linuxカーネルの軽量化を目指す

前提

この記事で扱っているカーネルlinux-3.3.8-gentooです
このgentoowindows xp上のvirtualboxで動かしています
menuconfigで既にチェックがついていた場合は書いてません

経緯

2chgentooのスレを見ていると
http://engawa.2ch.net/test/read.cgi/linux/1318891441/ から引用

371 :login:Penguin:2012/02/17(金) 22:37:54.52 ID:2t6GauCx
    ls -sh /boot/kernel-3.2.1-gentoo-r2
    4.4M /boot/kernel-3.2.1-gentoo-r2

    ほとんどモジュール作っていないけれど、
    このサイズって大きい?

372 :login:Penguin:2012/02/17(金) 23:46:22.68 ID:K5T+AqfZ
    # lsmod
    Module Size Used by
    autofs4 22972 2
    nvidia 12059806 30
    pl2303 12301 0
    usbserial 28301 1 pl2303
    # ls -hs /boot/kernel-3.2.1-gentoo-r2
    2.2M /boot/kernel-3.2.1-gentoo-r2

    LZMA だけど、おれの2倍かな。 

気になるものがあった
私のはどれぐらいかなと見てみると

% lsmod
Module                  Size  Used by

モジュールは一切ない

% ls -hs /boot/linux-3.3.8-gentoo-3
4.9M /boot/linux-3.3.8-gentoo-3

今の時代の記憶媒体にしては多くはないと言えそうだけど容量が多いとそれだけ機能が多くて起動に時間がかかりそうなので減らすことにした
ちなみに

377 :372:2012/02/18(土) 14:11:55.41 ID:Y+qaoTIn
    組み込んだドライバは一応こんだけあります。
    $ lspci -k | grep driver
    Kernel driver in use: pcieport
    Kernel driver in use: pcieport
    Kernel driver in use: ahci
    Kernel driver in use: ohci_hcd
    Kernel driver in use: ohci_hcd
    Kernel driver in use: ehci_hcd
    Kernel driver in use: ohci_hcd
    Kernel driver in use: ohci_hcd
    Kernel driver in use: ehci_hcd
    Kernel driver in use: piix4_smbus
    Kernel driver in use: snd_hda_intel
    Kernel driver in use: ohci_hcd
    Kernel driver in use: k10temp
    Kernel driver in use: nvidia
    Kernel driver in use: snd_hda_intel
    Kernel driver in use: r8169
    Kernel driver in use: r8169 

これを参考にやってみると

# lspci -k|grep driver
        Kernel driver in use: ata_piix
        Kernel driver in use: e1000
        Kernel driver in use: snd_intel8x0
        Kernel driver in use: ohci_hcd
        Kernel driver in use: ahci

それでは試しにやってみる

現在の.configはこれです
https://gist.github.com/3179218
gentooを初めてインストールした時からのを引き継いでいる奴です
確か初めてインストールしたのは2ヶ月ぐらい前だったかな
その話は置いといて、というようにどっかに.confgをバックアップしてから

% cd /usr/src/linux

カーネルのソースがある場所に移動して

# make mrproper

.configやらコンパイル済みのものとか色々消して初期化する
次にどこで知ったか覚えてないけど

# make allnoconfig

これで必要最低限のもの以外はno、つまり余計な機能がない.configが出来上がるらしい
とりあえず最低限の場合はどれぐらいの容量か知りたいのでカーネルを作ることにします
ちなみに http://itpro.nikkeibp.co.jp/members/SI/oss/20031024/3/ こことかを参考にV=1を足すとemerge -v のようになるらしい

# make V=1

いつもより早くコンパイルが終わりました
さて、こんな感じで作ったとしましてさっそく容量を見てみます

% ls -hs ./arch/x86/boot/bzImage
784K ./arch/x86/boot/bzImage

びっくりするぐらい減りました
試しにこれを使ってbootしてみることにします

# mount /boot
# cp ./arch/x86/boot/bzImage /boot

起動するために再起動してgrubが立ち上がったらcを押してgrub shellを立ち上げます
もしgrubを使っていない場合は各自の環境にあわせてください
そして私の環境ですと

grub> kernel (hd0,0)/bzImage root=/dev/sda3
grub> boot

これで試しにbootをしてみます
すると1秒も満たないで案の定、カーネルパニックを起こしました

nts only.
bio: create slab <bio-0> at 0
Switching to clocksource pit
platform rtc_cmos: registered platform RTC device (no PNP device found)
highmem bounce pool size: 64 pages
io scheduler noop registered (default)
serio: i8042 KBD port at 0x60,0x64 irq 1
serio: i8042 AUX port at 0x60,0x64 irq 12
mousedev: PS/2 mouse device common for all mice
List of all partitions:
No filesystem could mount root, tried:
Kernel panic - not syning: VFS: Unable to mount root fs on unknown-block(0,0)
Pid: 1, comm: swapper Not tainted 3.3.8-gentoo #1
Call Trace:
 [<c10fe5f2>] ? panic+0x6e/0x14a
 [<c1153a93>] ? mount_block_root+0x217/0x22b
 [<c11536e4>] ? do_one_initcall+0x12e/0x12e
 [<c1002930>] ? sys_rt_sigreturn+0x50/0xb0
 [<c1153af8>] ? mount_root+0x46/0x5a
 [<c11536e4>] ? do_one_initcall+0x12e/0x12e
 [<c1153c1a>] ? prepare_namespace+0x10e/0x14a
 [<c1073a9f>] ? sys_access+0x1f/0x30
 [<c11537e7>] ? kernel_init+0x103/0x10f
 [<c11009d6>] ? kernel_thread_helper+0x6/0xd
_

画面上にはこんな画面で止まっていました
ようはrootに指定したやつがマウントできなかったわけですね
恐らくドライバがなかっただけだと思うのでこれからは
http://humming.dip.jp/cgi-bin/usemod.pl?AllNoConfig
このサイトで大まかに有効するものを参考にしながら必要なものを追加していくとしましょう
そして参考になりそうなサイトが見つかりました
http://swift.siphos.be/linux_sea/ch07.html#idp35213232
これによると(0,0)などの1桁目が0のエラーが出ていた場合はドライバがないなどでデバイスを認識できない場合に起こるらしいですのでそのようなドライバを追加していくことにします
ちなみに(8,3)などの1桁目が8のエラーが出ていた場合はデバイスは認識できるけどファイルシステムなどの問題でダメな場合に出るらしい
話を戻してthe kernel configuration is missing drivers for your HDD controlleにあったcase5を見てみると
https://forums.gentoo.org/viewtopic-t-801465.html
ここに一番解決に近そうな設定例があったのでそれを参考にしました
ちなみに私の環境のvirtualboxIDEではなくSATAでhddをエミュレートしてます
それでは一度システムを落としてカレントディレクトリが変わっているので

% cd /usr/src/linux

カーネルのソースのあるディレクトリに移動します

# make menuconfig

これで.configをいじっていきます
とりあえず今はrootに指定したものを認識できるようにして起動できるところまでを目指しています
まずは私の環境だとファイルシステムに/bootはext2で/はext3を使っているのでそれを有効にします

File systems -> [*] Second extended fs support
File systems -> [*] Ext3 journalling file system support

このようにいくつか設定したら

# make V=1
# sudo mount /boot
# cp arch/x86/boot/bzImage /boot
# shutdown -r now

grubが立ち上がったらcキーでgrub shellへ

grub> kernel (hd0,0)/bzImage root=/dev/sda3
grub> boot

こうやって起動できるか確かめていく事の繰り返しをしていきます
そして最終的に私の環境で追加して起動できたのは

File systems -> [*] Second extended fs support
File systems -> [*] Ext3 journalling file system support
Bus options (PCI etc.) -> [*] PCI support
Device Drivers -> SCSI device support -> [*] SCSI device support
Device Drivers -> SCSI device support -> [*] SCSI disk support
Device Drivers -> [*] Serial ATA and Parallel ATA drivers
Device Drivers -> [*] Serial ATA and Parallel ATA drivers -> [*] AHCI SATA support
Excutable file formats / Emulations -> [*] Kernel support for ELF binaries

これでとりあえず起動はできるようになりました
openrcが立ち上がるまでの時間は一瞬になりました
ちなみにこの時点で

% ls -hs /boot/bzImage
1.2M /boot/bzImage

これぐらいの容量があります
次はネットワーク関連を使えるようにします
よくわかってませんが以下のをサイトに習って有効にしときます

[*] Networking support
[*] Networking support -> Networking options -> [*] Packet socket
[*] Networking support -> Networking options -> [*] Unix domain sockets
[*] Networking support -> Networking options -> [*] TCP/IP networking

次にLANカードのドライバ、私の環境だとe1000のドライバを入れます
これはどうやって調べたかというと

# lspci -k
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.1 IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)
        Kernel driver in use: ata_piix
00:02.0 VGA compatible controller: InnoTek Systemberatung GmbH VirtualBox Graphics Adapter
00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
        Subsystem: Intel Corporation PRO/1000 MT Desktop Adapter
        Kernel driver in use: e1000
00:04.0 System peripheral: InnoTek Systemberatung GmbH VirtualBox Guest Service
00:05.0 Multimedia audio controller: Intel Corporation 82801AA AC'97 Audio Controller (rev 01)
        Subsystem: Intel Corporation Device 0000
        Kernel driver in use: snd_intel8x0
00:06.0 USB controller: Apple Computer Inc. KeyLargo/Intrepid USB
        Kernel driver in use: ohci_hcd
00:07.0 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08)
00:0d.0 SATA controller: Intel Corporation 82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (rev 02)
        Kernel driver in use: ahci

このコマンドを実行した時にEthernet controllerと書かれている下に

        Kernel driver in use: e1000

こう書いてあったのでそう推測できます
そして色々ドライバがあってどれを有効にするかわかりませんがそういった場合は
make menuconfigをした後に「/」を使ってe1000で検索するとそれらしいものが見つかるので有効にするだけです

[*] Device Drivers -> [*] Network device support -> [*] Ethernet driver support -> [*] Intel(R) PRO/1000 Gigabit Ethernet support

これで私の環境でインターネットに接続するのに必要であろうものは有効にできたのでコンパイルして/bootに配置してできあがったカーネルでbootしてみます
そしてpingを外に向けて打てたら成功です
ちなみにいちいちコンパイルしないで欲しい機能を全て有効にした後にコンパイルしたほうが時間の節約になると思います
ですが今回は1つ1つデバッグをしていきたいのでこのような方法になっていますのであしからず
ちなみに現段階の容量は

% ls -hs /boot/bzImage
1.7M /boot/bzImage

次にopenrcで色々起動している時にudevが使えてなくて色々とエラーが出ているのでudevを使えるようにします
http://www.gentoo.org/doc/ja/udev-guide.xml
これを参考に

General setup -> [*] Configure standard kernel features (expert users)
File systems -> Inotify support for userspace
File systems -> Pseudo filesystems -> [*] Tmpfs virtual memory file system support (former shm fs)

これでエラーが出ないことが確認できました

さて、次は解像度を好きに設定して起動できるようにしたいので
http://dev.gentoo.org/~spock/projects/uvesafb/
これを参考にしながら先ほどのようにやっていきましょう

Device Drivers -> [*] Connector - unified userspace <-> kernelspace linker
Device Drivers -> Graphics support -> [*] Support for frame buffer devices
Device Drivers -> Graphics support -> [*] Support for frame buffer devices -> [*] Userspace VESA VGA graphics support
Device Drivers -> Graphics support -> Console display driver support -> [*] Framebuffer Console support
General setup -> [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
General setup -> (/usr/share/v86d/initramfs) Initramfs source file(s)

ちなみにUserspace(略)はConnector(略)に依存してます
依存しているものがONになっていないとmenuconfigで表示されないみたいですね
/bootディレクトリに置けたら
再起動をしてgrub shellで

grub> kernel (hb0,0)/bzImage root=/dev/sda3 video=uvesafb:1280x1024-32,mtrr:3,ywrap
grub> boot

こんな感じで実際に解像度がその大きさになるか試します
そろそろ打つのが面倒になってくると思うのでgrub.confに書いてもいいと思います

次にSWAPを使えるようにします

General setup -> [*] Support for paging of anonymous memory (swap)

できたら

% free
             total       used       free     shared    buffers     cached
 Mem:       1035528     133560     901968          0      12152      65088
 -/+ buffers/cache:      56320     979208
 Swap:      2620408          0    2620408

こんな感じで確認します

次にzcat /proc/config.gzでカーネルの構築に使った.configを表示できるようにしたいので

General setup -> [*] Kernel .config support
General setup -> [*] Enable access to .config through /proc/config.gz

できたらzcat /proc/config.gzで表示できるか確認します

cgroupを使えるようにしたいので

General setup -> [*] Automatic process group scheduling
General setup -> [*] Control Group support -> この中を全て [*]

できたらls /sys/fs/cgroupなどにcgroup関連のファイルがあるか確認します

これで私の場合でCUIで使うなら前の環境とほぼ変わらなくなりました
もしかしたら必要な何かをしていないかもしれませんが。
ちなみに現段階の容量は

% ls -hs /boot/bzImage
1.9M /boot/bzImage

後はデスクトップ環境でも問題なく使えるようにするだけです
音がなるようにサウンドカードのドライバを入れます

# lspci -k
(前略)
00:05.0 Multimedia audio controller: Intel Corporation 82801AA AC'97 Audio Controller (rev 01)
        Subsystem: Intel Corporation Device 0000
        Kernel driver in use: snd_intel8x0
(後略)

これを参考にmakeconfigでsnd_intel8x0を探しました

Device Drivers -> [*] Sound card support
Device Drivers -> [*] Sound card support -> [*] Advanced Linux Sound Architecture
Device Drivers -> [*] Sound card support -> [*] Advanced Linux Sound Architecture -> [*] PCI sound devices -> [*] Intel/SiS/nVidia/AMD/ALi AC97 Controller

これだけだとなぜかmplayerで音がならなくてこのようなエラーのようなメッセージを吐きました

(前略)
[AO_ALSA] alsa-lib: pcm_dmix.c:985:(snd_pcm_dmix_open) unable to create IPC semaphore
[AO_ALSA] Playback open error: Function not implemented
(後略)

なので http://forums.gentoo.org/viewtopic-t-689287.html を参考にしてSystem V IPCを有効にします

General setup -> [*] System V IPC

できたらmplayerなどで音を鳴らして確認します

この時点で

% startx

をしてもウィンドウマネージャーは起動しますがなぜかキー入力とマウスが効かないのドライバを入れますが
その前にウィンドウマネージャーが固まっているだけの可能性もあるので時計が動いているか確認するか
http://d.hatena.ne.jp/gikogeek/20080220
このサイトを参考にssh経由でXのソフトを起動して試してみます

% export DISPLAY=:0.0
% nohup xterm &

すると問題なくxtermが表示されるので単にキー入力が効かないだけだとわかるので根気よく調べることにします
すると http://www.asia-groove.com/~nong-khai/bbs2/read.php/ASIA/1313894166/
このサイトが参考になりそうだったので書いてあるとおりに

Device Drivers -> Input device support -> [*] Event interface

を有効にすれば問題なくキーボードが動きましたがマウスは動きませんでした
そこでマウスなのですが

Device Drivers -> Input device support -> [*] Mice

このようにドライバを入れても動かないのでUSBマウスなような気がするので
USBを使ったデバイスを探します

# lspci -k
(前略)
00:06.0 USB controller: Apple Computer Inc. KeyLargo/Intrepid USB
        Kernel driver in use: ohci_hcd
(後略)

これを見るとカーネルに埋め込んであるohci_hdcというドライバがあればよさそうなのでmenuconfigで「/」を使って探しました
後は http://www.gentoo.org/doc/ja/usb-guide.xml を参考にして

Device Drivers -> [*] USB support
Device Drivers -> [*] USB support -> [*] Support for Host-side USB
Device Drivers -> [*] USB support -> [*] OHCI HCD support
Device Drivers -> [*] HID Devices

それとDevice Drivers -> [*] HID Devices -> [*] USB Human Interface Device (full HID) supportで何とかしてるのかわかりませんが

Device Drivers -> Input device support -> [ ] Mice

このようにOFFにしてもマウスが問題なく動きました

とりあえずこれで私の用途だと今のところ問題がありませんが恐らくこれだけだとCDやUSBメモリを認識しないような気がします
それでも今のところは必要ないので今回はここまでにします
今回は既に設定してあるものは特にOFFにはしませんでしたが適当に見た程度だといくつか使わなさそうなドライバが勝手にONになっていたのでそれを削ればもう少し容量が減るかもしれません

というわけでここまでの設定をしたbzImageの容量

% ls -hs /boot/bzImage
2.1M /boot/bzImage

ここまでの設定をした.config
https://gist.github.com/3191305
最後に手動で有効にした設定一覧*1

File systems -> [*] Second extended fs support
File systems -> [*] Ext3 journalling file system support
Bus options (PCI etc.) -> [*] PCI support
Device Drivers -> SCSI device support -> [*] SCSI device support
Device Drivers -> SCSI device support -> [*] SCSI disk support
Device Drivers -> [*] Serial ATA and Parallel ATA drivers
Device Drivers -> [*] Serial ATA and Parallel ATA drivers -> [*] AHCI SATA support
Excutable file formats / Emulations -> [*] Kernel support for ELF binaries

[*] Networking support
[*] Networking support -> Networking options -> [*] Packet socket
[*] Networking support -> Networking options -> [*] Unix domain sockets
[*] Networking support -> Networking options -> [*] TCP/IP networking

[*] Device Drivers -> [*] Network device support -> [*] Ethernet driver support -> [*] Intel(R) PRO/1000 Gigabit Ethernet support

General setup -> [*] Configure standard kernel features (expert users)
File systems -> Inotify support for userspace
File systems -> Pseudo filesystems -> [*] Tmpfs virtual memory file system support (former shm fs)

Device Drivers -> [*] Connector - unified userspace <-> kernelspace linker
Device Drivers -> Graphics support -> [*] Support for frame buffer devices
Device Drivers -> Graphics support -> [*] Support for frame buffer devices -> [*] Userspace VESA VGA graphics support
Device Drivers -> Graphics support -> Console display driver support -> [*] Framebuffer Console support
General setup -> [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
General setup -> (/usr/share/v86d/initramfs) Initramfs source file(s)

General setup -> [*] Support for paging of anonymous memory (swap)

General setup -> [*] Kernel .config support
General setup -> [*] Enable access to .config through /proc/config.gz

General setup -> [*] Automatic process group scheduling
General setup -> [*] Control Group support -> この中を全て [*]

Device Drivers -> [*] Sound card support
Device Drivers -> [*] Sound card support -> [*] Advanced Linux Sound Architecture
Device Drivers -> [*] Sound card support -> [*] Advanced Linux Sound Architecture -> [*] PCI sound devices -> [*] Intel/SiS/nVidia/AMD/ALi AC97 Controller

General setup -> [*] System V IPC

Device Drivers -> Input device support -> [*] Event interface

Device Drivers -> [*] USB support
Device Drivers -> [*] USB support -> [*] Support for Host-side USB
Device Drivers -> [*] USB support -> [*] OHCI HCD support
Device Drivers -> [*] HID Devices

一応確認しましたがもしかしたら記入漏れがあるかもしれません

余談

最初にhddを認識させるくだりとSystem V IPCで有効にして音をならすくだりとキー入力ができるようにするまでのくだりで何が足らないのか少なくとも1時間以上悩んでかなり苦労しました

*1:有効にした順