この章では、特定のカーネル関数を見たいとき、カーネルソースのどこから 探し始めればよいのかについて説明する。
本書は、C プログラミング言語の知識を前提とするものではなく、カーネルの動作 の仕組みを理解するのに Linux カーネルソースを持っていることを要求するものでも ない。とはいえ、カーネルソースを見て、Linux オペレーティングシステムへの理解を 深める努力をすることはよい結果をもたらすことだろう。この章では、カーネルソース の概観を説明し、それらの構造や特定のコードを探す時の目安となるものについて 述べる。
メジャーな Linux ディストリビューション( Craftworks, Debian, Slackware, Red Hat などなど)ならどこでも、カーネルソースが同梱されている。通常、システム にインストールされた Linux カーネルは、そうしたソースからビルドされている。 やむを得ない事情から、それらのソースは少々古いものになりがちなので、 「ウェブと FTP サイト」で述べるウェブサイト から最新のソースを入手したいと考えるかもしれない。ソースコードは、 ftp://ftp.cs.helsinki.fi で保存されていて、それ以外のウェブサイトはすべてそのミラーである。 (訳注: 現在のプライマリサイトは、 http://www.kernel.org です。) それゆえ、Helsinki のウェブサイトに最新のソースがあることになるが、MIT や Sunsite でも決してひどく古いわけではない。
ウェブにアクセスできない場合でも、多くの CD-ROM ベンダがあり、それらが 世界のメジャーなウェブサイトのスナップショットを妥当な値段で提供している。 四半期や、あるいは毎月更新される定期購買サービスを提供しているベンダまである。 ローカルな Linux ユーザグループも、ソースコードの提供元である。
Linux カーネルソースは、非常にシンプルなバージョン番号管理をしている。
中央の番号、x.y.z の y が、偶数番号のカーネル(たとえば、
2.0.30)は、安定した、リリース版カーネルで、奇数番号のカーネル(たとえば、2.1.42)
は、開発版カーネルである。本書は、安定版 2.0.30 のソースツリーに基づいている。
開発版カーネルは最新機能のすべてを備え、最新デバイスをすべて
サポートしている。それらは安定しない場合があるかもしれず、それはあなたが
Linux に求めるものではないかもしれないが、Linux コミュニティーが最新版
カーネルを試しているということは重要である。それによって、最新版は
コミュニティー全体でテストされるからである。安定版でないカーネルを使う場合、
システム全体のバックアップは常に価値あるものであることを忘れないでほしい。
カーネルソースへの変更は、パッチファイルで配布される。パッチユーティリティ は、ソースファイルのセットに一連の編集を加えるために使用される。たとえば、 2.0.29 のカーネルソースツリーを持っていて、2.0.30 のソースツリーに移行したい 場合は、2.0.30 のパッチを入手して、そのパッチ(ソース編集スクリプト)をその カーネルソースに適用すればよい。
$ cd /usr/src/linux $ patch -p1 < patch-2.0.30
そうすれば、ソースツリー全体を、おそらく低速なシリアル回線を使ってコピーしな くても済む。カーネルパッチ(正式版もそうでないものも)の便利な入手先は、 http://www.linuxhq.web.site である。
ソースツリーの最上ディレクトリである
/usr/src/linux には、
(次のような)多くのディレクトリがある。
<#if output="html">
(訳注: JF サイト上でご覧の場合、一部のファイルしか表示されません。 ソース全体を見るには、 日本語訳についてを参照してください。) <#/if>
archarch サブディレクトリには、アーキテクチャ(architecture)固有の
カーネルコードが含まれている。
さらに深いサブディレクトリがあり、たとえば、i386 や alpha と
いったサポートするアーキテクチャごとに分かれている。
includeinclude サブディレクトリには、カーネルコードをビルドするのに必要な
インクルードファイル(include files)の大部分が含まれている。
さらに深いサブディレクトリもあり、サポートするアーキテクチャごとのファイルが含
まれている。include/asm サブディレクトリは、たとえば include/asm-i386 といったそのアーキテクチャに必要な実際の include
ディレクトリへのソフトリンク(シンボリックリンク)となっている。
アーキテクチャを変更するには、カーネルの makefile を編集し、Linux カーネル
設定プログラムを再実行する必要がある。
initこのディレクトリには、カーネルの初期化(initialization)コードが含まれているの で、カーネルの動作の仕組みをこれから見ようとする場合はよい出発点になる。
mmこのディレクトリには、メモリ管理(memory management)コードのすべてが含まれてい
る。アーキテクチャ固有のメモリ管理コードについては、arch/i386/mm/fault.c といった arch/*/mm ディレクトリ以下にある。
driversシステム上のデバイスドライバ(device drivers)は、すべてこのディレクトリに置かれ
ている。
このディレクトリはさらに再分割され、block といったデバイスドライバ
のクラスごとに分かれている。
ipcこのディレクトリには、カーネルのプロセス間通信(inter-process communications)に 関するコードが含まれている。
modulesこのディレクトリは、ビルドされたモジュール(module)を保存するためだけに使用され ている。
fsファイルシステム(file system)コードのすべてはここに置かれている。
このディレクトリはさらに再分割されていて、vfat や ext2 と
いったサポートするファイルシステムごとに分かれている。
kernel主要なカーネル(kernel)コードが置かれている。ここでも、アーキテクチャ固有の
カーネルコードは、arch/*/kernel にある。
netカーネルのネットワーク(network)関係のコードが置かれている。
libこのディレクトリには、カーネルのライブラリ(library)コードが含まれている。
アーキテクチャ固有のライブラリは、arch/*/lib で見つけることができる。
scriptsこのディレクトリには、カーネルを設定するときに使用されるスクリプト(script)
(たとえば、awk や tk スクリプト)が含まれている。
Linux カーネルくらい巨大で複雑なプログラムになると、見ようとする者を威圧 するかのような感がなくもない。まるで辿るべき一端がなくて、解けない球状の 巻き糸のようである。カーネルの一部を見ていると、しばしばいくつかの他の関連 ファイルへと導かれて、すぐに自分で何を探していたのか分からなくなる。以下では、 節に付けた題名について、ソースツリーのどこを見れば最良かヒントを述べる。
Intel ベースのシステムなら、カーネルが起動するのは、loadlin.exe
か LILO がカーネルをメモリにロードして制御をカーネルに渡したときである。
その部分に関しては、
arch/i386/kernel/head.S を見ること。head.S はアーキテクチャ固有の設定をいくつか行ってから、
init/main.c 内にある main() ルーチンへジャンプする。
これに関するコードの大部分は mm にあるが、アーキテクチャ固有の
コードは arch/*/mm にある。ページフォルト処理コードは
mm/memory.c にあり、メモリマッピングとページキャッシュのコードは
mm/filemap.c にある。
バッファキャッシュは、mm/buffer.c(訳注:
fs/buffer.c) で実装されており、
スワップキャッシュは
mm/swap_state.c と
mm/swapfile.c にある。
関連する汎用コードの大部分は、kernel にあるが、アーキテクチャ固有
のコードは arch/*/kernel にある。スケジューラは
kernel/sched.c にあり、fork のコードは
kernel/fork.c にある。
ボトムハーフ処理のコードは
include/linux/interrupt.h に含まれている。
task_struct データ構造体は、
include/linux/sched.h にある。
PCI 仮想ドライバは
drivers/pci/pci.c にあり、システム全体の定義
は
include/linux/pci.h にある。個々のアーキテクチャには固有の PCI
BIOS コードがあり、Alpha AXP のものは
arch/alpha/kernel/bios32.c にある。
これらはすべて ipc にある。すべての System V IPC オブジェクトは
ipc_perm データ構造体を含んでいるが、これは
include/linux/ipc.h にある。System V メッセージは
ipc/msg.c で実装されていて、
共有メモリは
ipc/shm.c 、セマフォは
ipc/sem.c にある。
パイプは、ipc/pipe(訳注:
fs/pipe.c) で実装されている。
カーネルの割り込み処理コードは、ほとんどすべてマイクロプロセッサ(そして、
しばしばプラットフォーム)固有のものである。Intel の割り込み処理コードは、
arch/i386/kernel/irq.c にあり、その定義は
include/asm-i386/irq.h にある。
Linux カーネルソースコードの大部分は、デバイスドライバのものである。
Linux デバイスドライバのソースのすべては、drivers にあるが、その
ディレクトリはデバイスタイプによってさらに分岐している。
/blockIDE(
ide.c)
などのブロックデバイスドライバ。ファイルシステムを置くことができる
すべてのデバイスがどのように初期化されるのかを見たい場合は、
drivers/block/genhd.c にある device_setup() を見るべき
である。
それは、ハードディスクの初期化だけでなく、NFS ファイルシステムをマウントする
ためにネットワークを必要とする際にはネットワークデバイスをも初期化する。
ブロックデバイスには、IDE ベースと SCSI ベースの両方のデバイスが含まれる。
/charここは、tty やシリアルポート、マウスなどのキャラクタベースのデバイスを 探すときに見る場所である。
/cdromLinux 上のすべての CD-ROM のコード。特定の CD-ROM デバイス(たとえば、
Soundblaster
CD-ROM)がここに置かれている。IDE CD ドライバは drivers/block の
ide-cd.c にあり、SCSI CD ドライバは drivers/scsi の
scsi.c にあるので、注意すること。
/pciここには、PCI 仮想ドライバのためのソースがある。PCI サブシステムがマップされ
初期化される方法を見るのに適した場所である。
arch/alpha/kernel/bios32.c にある Alpha AXP PCI 修正(fixup)コード
も見るに値するだろう。
/scsiここは、SCSI コードのすべてがある場所であり、Linux でサポートされている SCSI デバイスのすべてのドライバが置かれている場所である。
/netここは、DEC Chip 21040 PCI イーサネットドライバ(
tulip.c)といったネットワークデバイスドライバが見つかる場所である。
/soundここは、すべてのサウンドカードドライバがある場所である。
EXT2 ファイルシステムのソースはすべて、fs/ext2 ディレクトリにあり、
データ構造の定義は、
include/linux/ext2_fs.h と
ext2_fs_i.h,
ext2_fs_sb.h にある。
仮想ファイルシステムのデータ構造体は、
include/linux/fs.h に記述されており、そのコードは fs/* に
ある。バッファキャッシュは、update デーモンと一緒に
fs/buffer.c で実装されている。
ネットワークのコードは、net に保存されていて、その大部分の include
ファイルは include/net にある。BSD ソケットコードは、
net/socket.c にあり、IP version 4 INET ソケットコードは、
net/ipv4/af_inet.c にある。
汎用のプロトコルサポートコード(sk_buff 処理ルーチンなど)は、
net/core にあり、TCP/IP ネットワークのコードは net/ipv4
にある。ネットワークデバイスドライバは、drivers/net にある。
カーネルモジュールコードは、カーネル内にある部分とその modules の
パッケージに入っている部分とがある。カーネルコードはすべて
kernel/module.c にあり、
そのデータ構造とカーネルデーモンである kerneld の
メッセージは、
include/linux/module.h と
include/linux/kerneld.h とにそれぞれ入っている。
ELF オブジェクトファイルの構造は、
include/linux/elf.h で見ることができる。