Linuxカーネルは,「モノリシック・カーネル」という種類のカーネルです。モノリシック・カーネルとは,機能のすべてを1つのプログラムとして構成し,動作させるカーネルのことです。モノリシックとは一枚岩を表す「モノリス」という言葉からきています。

 モノリシック・カーネルの対語が「マイクロカーネル」です。マイクロカーネルは,各機能を独立したプログラムに分割し,それらのプログラムを協調稼働させてサービスを提供する仕組みとなっています。これにより,構成を柔軟に調整したり,マルチプロセッサの効率的な利用が可能になるなどの利点があるとされます。

 逆にモノリシック・カーネルは,動作中に機能追加をしたり,挙動を変更したりできない問題があるとされていました。事実,初期のUNIX系OSでは,必要なデバイス・ドライバをすべてカーネルに組み込んでビルドしておく必要がありました。これでは,たまにしか使わない周辺機器向けのドライバも常に組み込んでおかねばなりません。これはメモリー領域の無駄使いです。かといって,その周辺機器を接続するたびにカーネルをビルドし直すのも面倒です。

 そのため,Linuxを含む最近のモノリシック・カーネルのOSでは,デバイス・ドライバの追加や削除を動的に実施する仕組みを備えています。Linuxでは,この機構を「モジュール機構」と呼びます。今回は,このモジュール機構について解説します。

カーネル機能を分離できる

 モジュール機構を利用すると,「モジュール」の形で分割したカーネル機能の一部を,動的に組み込んだり,切り離したりできます。これが特に役立つのは,PCカードやUSB機器などのデバイスです。

 モジュール機構が無いと,対応デバイス・ドライバが無い機器を取り付けたときにカーネルの入れ替えなければなりません。機器のドライバが必要になるからです。PCI機器を装着する場合は,通常,PCの電源断が必要になりますから,(ビルドの手間はかかるとしても)そのときにカーネルを入れ替えても支障はないかもしれません。

 しかし,PCカードやUSB機器などは,コンピュータを再起動せずともデバイスの取り付け/取り外しができる「活線挿抜」が可能になっています。そのため,これらの機器を手軽に,かつ効率的に利用するには,対応するデバイス・ドライバを動的に組み込んだり,切り離したりできるモジュール機構が欠かせません。

 なお,LinuxはマイクロカーネルOSではありませんから,プロセス・スケジューラやメモリー管理機構といった,システムの核となる部分をモジュールとして分離することはできません。また,カーネルのデバッグ機構などもあらかじめビルド時に組み込んでおく必要があります。しかし,それ以外のもの,例えばデバイス・ドライバやファイル・システム,ネットワーク関連の機能などはモジュールとして分離できます。

モジュールの機能を使うには

 モジュール機構の詳細を見る前に,カーネルがなぜ,モジュールとして分離した機能を利用できるのかを考えてみましょう。

 プログラムは一般に,ハード・ディスクなどの補助記憶装置からメモリー上に読み込まれます。その後,読み込まれたプログラムは先頭から順に実行されます。しかし時には,指定されたメモリー・アドレスにジャンプして,そこに格納されているプログラムを実行することもあります。例えば,システム・コールを発行した場合や,ライブラリの関数を実行した場合などです。

 これらのジャンプ先メモリー・アドレスは,プログラムで指定しておく必要がありますが,メモリー・アドレスを直接指定するのは分かりにくいため,機能名などを元にした分かりやすい文字列(シンボルやラベルと呼ばれる)を使うのが一般的です。カーネルでは,カーネルの関数名やシステム・コール名を元にしたシンボルを使ってジャンプします。

 Linuxカーネルでどのようなシンボルを利用しているかは,/proc/ksymsファイルで調べられます(2.6カーネルでは /proc/kallsymsファイル)。メモリー管理の回で説明したように,LinuxカーネルはIA-32アーキテクチャの場合は4Gバイトのメモリー空間のうち,最後の1Gバイトのところ(0xc0000000以降)にロードされています。そのため,各シンボルに対応するメモリー・アドレスも,この領域内にあるはずです(図1)。

$ cat /proc/ksyms
c038be8c mmu_cr4_features_Rsmp_dad5638d
c0323364 acpi_disabled_Rsmp_1a45cb6c
c0323864 i8253_lock_Rsmp_ac2d2492
c0105358 machine_real_restart_Rsmp_3da1b07a
c01052b0 default_idle_Rsmp_92897e3d
c038c3c0 drive_info_Rsmp_744aa133
c03232c0 boot_cpu_data_Rsmp_4a8db2ac
c038be90 MCA_bus_Rsmp_f48a2c4c
c0115630 __verify_write_Rsmp_203afbeb
c0105760 dump_thread_Rsmp_ae90b20c
c010d298 dump_fpu_Rsmp_f7e7d3e6
c010d33c dump_extended_fpu_Rsmp_a9c2ac9b
c0115ecc __ioremap_Rsmp_9eac042a
c0115fb0 iounmap_Rsmp_5fb196d4
:
図1●Linuxカーネルが利用するシンボル
/proc/ksymsファイルを調べると,カーネル内の関数やシステム・コールのシンボルと,メモリー・アドレスの対応が分かります。

 一度メモリーに読み込んだカーネルのシンボル情報はこのように固定されています。モジュールを組み込むときは,メモリー内にモジュールを読み込んで,このシンボル情報に新たに追加することになるのです。そうすると,モジュールで追加した機能が利用できるというわけです。