<!--Chapter 12 Modules-->
<sect>モジュール<label id="chapter_m">
<p>
<figure><ph vspace="1"><img src="./The-Linux-Kernel-images/penguin2.gif">
</figure>

<!--
This chapter describes how the Linux kernel can dynamically load functions,
for example filesystems, only when they are needed. 
-->
<p>この章では、Linux カーネルが、ファイルシステムなどの機能を、必要な時だけ
動的にロードする仕組みについて説明する。

<!--
Linux is a monolithic kernel; that is, it is one, single, large program where 
all the functional components of the kernel have access to all of its internal
data structures and routines. The alternative is to have a micro-kernel
structure where the functional pieces of the kernel are broken out into
separate units with strict communication mechanisms between them. This
makes adding new components into the kernel via the configuration process
rather time consuming. Say you wanted to use a SCSI driver for an NCR 810
SCSI and you had not built it into the kernel. You would have to configure
and then build a new kernel before you could use the NCR 810. There is an
alternative, Linux allows you to dynamically load and unload components of
the operating system as you need them. Linux modules are lumps of code
that can be dynamically linked into the kernel at any point after the system
has booted. They can be unlinked from the kernel and removed when they
are no longer needed. Mostly Linux kernel modules are device drivers,
pseudo-device drivers such as network drivers, or file-systems. 
-->
<p>Linux は、モノリシックなカーネル(monolithic kernel)を使用している。すなわ
ちそれは、単一で巨大なプログラムであり、そこでは、カーネルのあらゆる機能別
コンポーネントが、すべての内部データ構造やルーチンにアクセスできる。
それとは反対の仕組みとして、マイクロカーネル(micro-kernel)構造がある。その
場合、カーネルの機能別部分は、個別のユニットに分割され、ユニット間での厳格な
通信メカニズムが設定される。モノリシックカーネルでは、新規コンポーネントを
カーネルに追加するには、その設定プロセスを経由するので、やや時間がかか
る。たとえば、NCR 810 SCSI の SCSI ドライバを使いたいのだが、まだそれをカーネル
に組み込んでいないとする。その際は、新しいカーネルを設定し、ビルドすることで、
はじめて NCR 810 が使用できるようになる。
しかし、違う選択肢も存在する。Linux では、必要に応じて、オペレーティング
システムのコンポーネントを動的にロードしたり、アンロードしたりできる。
Linux カーネルモジュール(module)とは、システム起動後ならいつでも動的にカーネル
にリンクすることができるコード群である。それらは、必要がなくなればカーネルとの
リンクを解消して削除することができる。大部分の Linux カーネルモジュールは、
デバイスドライバや、ネットワークドライバなどの仮想ドライバ、あるいはファイル
システムなどである。

<!--
You can either load and unload Linux kernel modules explicitly using the
insmod and rmmod commands or the kernel itself can demand that the kernel
daemon (kerneld) loads and unloads the modules as they are needed. 
Dynamically loading code as it is needed is attractive as it keeps the kernel
size to a minimum and makes the kernel very flexible. My current Intel
kernel uses modules extensively and is only 406Kbytes long. I only
occasionally use VFAT file systems and so I build my Linux kernel to
automatically load the VFAT file system module as I mount a VFAT partition.
When I have unmounted the VFAT partition the system detects that I no
longer need the VFAT file system module and removes it from the system.
Modules can also be useful for trying out new kernel code without having to
rebuild and reboot the kernel every time you try it out. Nothing, though, is 
for free and there is a slight performance and memory penalty associated with
kernel modules. There is a little more code that a loadable module must
provide and this and the extra data structures take a little more memory.
There is also a level of indirection introduced that makes accesses of kernel
resources slightly less efficient for modules. 
-->
<p>Linux カーネルモジュールは、<tt>insmod</tt> や <tt>rmmod</tt> コマンドを
使用して、明示的にロードとアンロードが可能である。また、カーネル自身も、
カーネルデーモン(<tt>kerneld</tt>)によって、モジュールのロードとアンロードを
必要に応じて行うことができる。必要なときに動的にロードできるコードというのは、
カーネルのサイズを最小に抑え、それに柔軟性を与えるという意味で非常に魅力的な
機能である。わたしの現在の Intel カーネルはモジュールを広範に使っているので、
406 K バイトで済んでいる。VFAT ファイルシステムはたまにしか使わないため、
VFAT パーティションがマウントされた時に自動的に VFAT ファイルシステムがロード
されるように、わたしのカーネルはビルドされている。VFAT パーティションをアンマウ
ントしたとき、システムはわたしがもはや VFAT ファイルシステムモジュールを必要と
していないことを検出して、システムからそれを削除する。新しいカーネルコードを
試すときでも、試行のたびにカーネルをリビルドして再起動をかける必要がないので、
その点でもモジュールは便利である。しかし、その見返りとして、カーネルモジュール
を使うと若干のパフォーマンスの低下とメモリの消費が起こる。ローダブルモジュール
にするために提供しなければならないコードが少量あり、そのコードと付加的なデータ
構造とが加わるために、メモリの消費量がやや増加する。また、あるレベルで
間接処理が導入されるので、モジュールの場合、カーネルリソースへのアクセスが
やや非効率になる。

<!--
Once a Linux module has been loaded it is as much a part of the kernel as
any normal kernel code. It has the same rights and responsibilities as any
kernel code; in other words, Linux kernel modules can crash the kernel just
like all kernel code or device drivers can. 
-->
<p>Linux モジュールは、いったんロードされると、通常のカーネルコードと同様に
カーネルの一部となる。すなわち、他のカーネルコードと同一の権利と責任を持つ。
言い換えると、Linux カーネルモジュールは、すべてのカーネルコードやデバイス
ドライバと同様に、カーネルをクラッシュさせることもできる。

<!--
So that modules can use the kernel resources that they need, they must be
able to find them. Say a module needs to call kmalloc(), the kernel
memory allocation routine. At the time that it is built, a module does not
know where in memory kmalloc() is, so when the module is loaded, the
kernel must fix up all of the module's references to kmalloc() before the
module can work. The kernel keeps a list of all of the kernel's resources in
the kernel symbol table so that it can resolve references to those resources
from the modules as they are loaded. Linux allows module stacking, this is
where one module requires the services of another module. For example, the
VFAT file system module requires the services of the FAT file system
 module as the VFAT file system is more or less a set of extensions to the
FAT file system. One module requiring services or resources from another
module is very similar to the situation where a module requires services and
resources from the kernel itself. Only here the required services are in
another, previously loaded module. As each module is loaded, the kernel
modifies the kernel symbol table, adding to it all of the resources or symbols
exported by the newly loaded module. This means that, when the next
module is loaded, it has access to the services of the already loaded
modules. 
-->
<p>モジュールが必要なカーネルリソースを使用するためには、まずそれらのリソースを
見つけだす必要がある。たとえば、モジュールが <tt>kmalloc()</tt> やカーネルメモ
リ割り当てルーチンを呼び出す必要がある場合などを考えてほしい。ビルドされた時点
では、モジュールは、メモリ内のどこに <tt>kmalloc()</tt> があるのかを知らない。
したがって、モジュールがロードされたとき、カーネルは、モジュールが動き出す前
に、モジュール内の <tt>kmalloc()</tt> への参照をすべて解決しなければならない。
カーネルは、カーネルのシンボルテーブル内にカーネルリソースのすべてのリストを保
持しているので、モジュールのロード時に、モジュールからのそうしたリソースへの参
照を解決することができる。
Linux では、モジュールをスタック化できる。すなわち、あるモジュールは、他の
モジュールのサービスを前提とし、そのサービスを利用できる。たとえば、VFAT ファイ
ルシステムモジュールは、FAT ファイルシステムのモジュールのサービスを必要とす
る。VFAT ファイルシステムは、多かれ少なかれ FAT ファイルシステムの拡張であるか
らである。他のモジュールのサービスやリソースを必要とするモジュールというのは、
モジュールがカーネルそのもののサービスやリソースを必要とする状況と非常に類似
している。必要とするサービスが、先にロードされた他のモジュールの中だけに
あるからである。個々のモジュールがロードされると、カーネルは、カーネルシンボル
テーブルを変更して、新しくロードされたモジュールがエクスポートしたリソースや
シンボルのすべてをそこに付け加える。これが意味するのは、次のモジュールがロード
されたとき、そのモジュールは既にロードされているモジュールのサービスにアクセス
出来るということである。

<!--
When an attempt is made to unload a module, the kernel needs to know that
the module is unused and it needs some way of notifying the module that it
is about to be unloaded. That way the module will be able to free up any
system resources that it has allocated, for example kernel memory or
interrupts, before it is removed from the kernel. When the module is
unloaded, the kernel removes any symbols that that module exported into
the kernel symbol table. 
-->
<p>モジュールをアンロードしようとするとき、カーネルはそのモジュールが使用されて
いないことを知る必要があり、モジュールにこれからアンロードされることを知らせる
方法をも必要とする。そして、その方法によって、モジュールは、カーネルから削除
される前に、カーネルメモリや割り込みなどの割り当てられたシステムリソースを
解放することが出来る。モジュールがアンロードされるとき、カーネルは、その
モジュールがカーネルシンボルテーブルにエクスポートしたすべてのシンボルを
削除する。

<!--
Apart from the ability of a loaded module to crash the operating system by
being badly written, it presents another danger. What happens if you load a
module built for an earlier or later kernel than the one that you are now
running? This may cause a problem if, say, the module makes a call to a
kernel routine and supplies the wrong arguments. The kernel can optionally
protect against this by making rigorous version checks on the module as it is
loaded. 
-->
<p>適切に書かれなかったために、ロードされたモジュールはオペレーティングシステム
をクラッシュさせることが出来るということの他にも、モジュールの使用は別の危険も
もたらす。現在使用しているカーネルよりも、古いか新しいバージョンのカーネル用に
ビルドされたモジュールをロードした場合、何が起こるだろうか？これが問題を
起こすのは、たとえばモジュールがカーネルルーチンをコールして、誤った引数を渡し
た場合である。カーネルは、オプションとしてではあるが、モジュールのロード時に
そのモジュールを厳格にバージョンチェックすることで、この問題が起こらないように
している。


<!--12.1  Loading a Module-->
<sect1>モジュールのローディング<label id="chapter_m_sect1">
<p>

<label id="figure12-1">
<!--              Figure 12.1: The List of Kernel Modules-->
<#if output="html">
<figure><ph vspace="1"><img src="./The-Linux-Kernel-images/figure12-1.gif">
</figure>
</#if>
<#unless output="html">
<verb>
+----module_list
|
|     module                          module
|  +----------+                    +----------+
+->| next     |------------------->| next     |
   |----------|                    |----------|
   | ref      |                 +->| ref      |
   |----------|                 |  |----------|
   | symtab   |------+          |  | symtab   |-------+
   |----------|      |          |  |----------|       |
   | name     |"fat" |          |  | name     |"vfat" |
   |----------|      |          |  |----------|       |
   | size     |      |          |  | size     |       |
   |----------|      |          |  |----------|       |
   | addr     | +----+          |  | addr     | +-----+ 
   |----------| |               |  |----------| |
   | state    | |  symbol_table |  | state    | |  symbol_table
   |----------| |  +----------+ |  |----------| |  +----------+
   |*cleanup()| +->| size     | |  |*cleanup()| +->| size     |
   +----------+    |----------| |  +----------+    |----------|
                   | n_symbols| |                  | n_symbols|
                   |----------| |                  |----------|
                   | n_refs   | |                  | n_refs   |
                   |----------| |                  |----------|
                   |          | |                  |          |
                   | symbols  | |                  | symbols  |
                   |          | |                  |          |
                   |----------| |                  |----------|
                   |references|-+                  |references|
                   |          |                    |          |
                   +----------+                    +----------+
</verb>
</#if>
<p>図表(12.1)カーネルモジュールのリスト

<!--
There are two ways that a kernel module can be loaded. The first way is to
use the insmod command to manually insert the it into the kernel. 
The second, and much more clever way, is to load the module as it is
needed; this is known as demand loading. 
When the kernel discovers the need for a module, for example when the user
mounts a file system that is not in the kernel, the kernel will request that 
the kernel daemon (kerneld) attempts to load the appropriate module. 
-->
<p>カーネルモジュールをロードする方法はふたつある。ひとつは、<tt>insmod</tt> 
コマンドによって手動でカーネルに組み込む方法。もうひとつの、ずっと賢明なやり
方は、必要に応じてモジュールを組み込む方法である。これは、デマンドローディ
ング(demand loading)と呼ばれる。ユーザがカーネル内に存在しないファイルシステム
をロードする時など、モジュールの必要性をカーネルが感知したとき、カーネルは、
カーネルデーモン(kerneld)に適切なモジュールをロードするようリクエストする。

<!--
The kernel daemon is a normal user process albeit with super user
privileges. When it is started up, usually at system boot time, it opens up an
Inter-Process Communication (IPC) channel to the kernel. This link is used
by the kernel to send messages to the kerneld asking for various tasks to
be performed. 
Kerneld's major function is to load and unload kernel modules but it is also
capable of other tasks such as starting up the PPP link over serial line when
it is needed and closing it down when it is not. Kerneld does not perform
these tasks itself, it runs the neccessary programs such as insmod to do the
work. Kerneld is just an agent of the kernel, scheduling work on its behalf. 
-->
<p>カーネルデーモンは、普通のユーザプロセスなのだが、スーパーユーザの権限を
持っている。通常はシステム起動時に実行が開始されるが、それが実行される
と、カーネルデーモンはカーネルに対するプロセス間通信(IPC)のチャンネルを開く。
このリンクはカーネルによって使用され、<tt>kerneld</tt> に対して様々なタスク
の実行を依頼するためのメッセージが送信される。
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/include/linux/kerneld.h" 
name="include/linux/kerneld.h">]<newline>
<tt>kerneld</tt> の主要な機能は、
カーネルモジュールのロードとアンロードだが、他のタスクの処理も可能である。
たとえば、必要なときにシリアル回線上で PPP リンクを開始し、必要がなくなったら
それを切断するといったこともできる。<tt>kerneld</tt> 自身がそうしたタスクを
実行するのではなく、<tt>insmod</tt> などの必要なプログラムを起動してそれに
仕事をさせる。<tt>kerneld</tt> は、カーネルの代理人(agent)のような存在であり、
カーネルを代理して仕事のスケジューリングを行う。

<!--
The insmod utility must find the requested kernel module that it is to load.
Demand loaded kernel modules are normally kept in
/lib/modules/kernel-version. The kernel modules are linked object
files just like other programs in the system except that they are linked as a
relocatable images. That is, images that are not linked to run from a
particular address. They can be either a.out or elf format object files.
insmod makes a privileged system call to find the kernel's exported
symbols. 
These are kept in pairs containing the symbol's name and its value, for
example its address. The kernel's exported symbol table is held in the first
module data structure in the list of modules maintained by the kernel and
pointed at by the module_list pointer. 
Only specifically entered symbols are added into the table, which is built
when the kernel is compiled and linked, not every symbol in the kernel is
exported to its modules. An example symbol is ``request_irq'' which
is the kernel routine that must be called when a driver wishes to take control
of a particular system interrupt. In my current kernel, this has a value of
0x0010cd30. You can easily see the exported kernel symbols and their
values by looking at /proc/ksyms or by using the ksyms utility. The
ksyms utility can either show you all of the exported kernel symbols or only
those symbols exported by loaded modules. insmod reads the module into its
virtual memory and fixes up its unresolved references to kernel routines and
resources using the exported symbols from the kernel. This fixing up takes
the form of patching the module image in memory. insmod physically writes
the address of the symbol into the appropriate place in the module. 
-->
<p><tt>insmod</tt> ユーティリティは、リクエストされたカーネルモジュールを
発見して、それをロードしなければならない。デマンドローディングでロードされた
カーネルモジュールは通常 <tt>/lib/modules/kernel-version</tt> に保存される。
カーネルモジュールは他のプログラムと同じくリンクされたオブジェクトファイル
なのだが、リロケータブル(relocatable)イメージとしてリンクされている点で異なる。
すなわち、特定の固定的なアドレスから実行されるようにリンクされたのではない
イメージであるということである。それらは <tt>a.out</tt> か <tt>ELF</tt> か
のいずれかのフォーマットを取る。<tt>insmod</tt> は、特権的なシステムコールを
発行して、カーネルによってエクスポートされたシンボルを見つけだす。
<newline>[see: sys_get_kernel_syms(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/kernel/module.c" 
name="kernel/module.c">]<newline>
それらは、シンボル名と、そのアドレスなどの値とを含んだペアとして保存される。
カーネルがエクスポートしたシンボルテーブルは、カーネルが管理するモジュール
のリストの最初の <tt><ref id="module" name="module"></tt> データ構造体に保持
され、その構造体は、<tt><ref id="module" name="module_list"></tt> ポインタに
よってポイントされる。
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/include/linux/module.h" 
name="include/linux/module.h">]<newline>
カーネルのシンボルテーブルに追加されるのは、明示的に追加が指示されたシンボル
だけである。シンボルテーブルは、カーネルのコンパイルとリンクがなされる時に
作成されるのだが、すべてのシンボルがモジュールにエクスポートされるわけでは
ない。
たとえば、<tt>request_irq</tt> というシンボルがあるが、これは、ドライバが特定の
システム割り込みを制御しようとする場合に呼び出されるカーネルルーチンである。
わたしの現在のカーネルでは、このシンボルは 0x0010cd30 という値を持っている。
エクスポートされたカーネルシンボルとその値を簡単に見るには、<tt>/proc/ksyms
</tt> を見るか、<tt>ksyms</tt> ユーティリティを使えばよい。
<tt>ksyms</tt> ユーティリティを使えば、エクスポートされたすべてのカーネル
シンボルを見ることも、ローダブルモジュールによってエクスポートされたシンボル
だけを見ることもできる。<tt>insmod</tt> コマンドは、
モジュールを仮想メモリから読み出して、カーネルがエクスポートしているシンボル
を使うことで、カーネルルーチンへの参照のなかでまだ解決されていない参照を
適宜解決(fixup)する。この解決は、メモリ内のモジュールイメージにパッチを当てる
という形式を取っている。<tt>insmod</tt> は、シンボルのアドレスをモジュール内の
適切な場所に書き込む。

<!--
When insmod has fixed up the module's references to exported kernel
symbols, it asks the kernel for enough space to hold the new kernel, again
using a privileged system call. The kernel allocates a new module data
structure and enough kernel memory to hold the new module and puts it at
the end of the kernel modules list. The new module is marked as
UNINITIALIZED. 
Figure  12.1 shows the list of kernel modules after two modules, VFAT and
VFAT have been loaded into the kernel. Not shown in the diagram is the first
module on the list, which is a pseudo-module that is only there to hold the
kernel's exported symbol table. You can use the command lsmod to list all
of the loaded kernel modules and their interdependencies. lsmod simply
reformats /proc/modules which is built from the list of kernel module
data structures. The memory that the kernel allocates for it is mapped into
the insmod process's address space so that it can access it. insmod copies
the module into the allocated space and relocates it so that it will run from
the kernel address that it has been allocated. This must happen as the
module cannot expect to be loaded at the same address twice let alone into
the same address in two different Linux systems. Again, this relocation
involves patching the module image with the appropriate addresses. 
-->
<p><tt>insmod</tt> によって、エクスポートされたカーネルシンボルに対するモジュー
ルの参照が解決されると、<tt>insmod</tt> は、再度特権的なシステムコールを使っ
て、新しいカーネルを保持するのに充分なスペースをくれるようカーネルに依頼する。
カーネルは、新規の <tt><ref id="module" name="module"></tt> データ構造体と、
新しいモジュールを保持するのに充分なメモリ容量を割り当てて、それをカーネル
モジュールリストの最後尾に置く。
その新しいモジュールは UNINITIALIZED とマークされる。
<newline>[see: sys_create_module(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/kernel/module.c" 
name="kernel/module.c">]<newline>
<ref id="figure12-1" name="図表(12.1)">では、VFAT と FAT のふたつのモジュール
がカーネルにロードされた後のカーネルモジュールのリストが示されている。
図表では示されていないが、リストの
先頭のモジュールは <tt>pseudo-module</tt> となっていて、これはカーネルの
エクスポートされたシンボルのテーブルを保持するためだけにそこに置かれているもの
である。<tt>lsmod</tt> コマンドを使えば、ロードされているすべてのモジュールと
その依存関係を表示することができる。<tt>lsmod</tt> は単に <tt>/proc/modules
</tt> を再構成しただけのもので、<tt>/proc/modules</tt> の方は、カーネルの 
<tt>module</tt> データ構造体のリストから作成されたものである。
モジュール用に割り当てられたメモリは、 <tt>insmod</tt> がモジュールにアクセス
できるよう、<tt>insmod</tt> プロセスのアドレス空間にマップされる。
<tt>insmod</tt> は、モジュールを割り当てられたアドレス空間にコピーして
モジュールの置き場所を変更することで、割り当てを受けたカーネルアドレス空間から
モジュールが実行されるようにする。
こうした処理が必要なのは、異なる Linux システム上ではモジュールを同じアドレス
にロードするよう要求できないだけでなく、同一システム上でも同じアドレスに
二度ロードするよう要求することはできないからである。このアドレスの変更の際
には、モジュールイメージが適切なアドレスを持つように修正がなされる。

<!--
The new module also exports symbols to the kernel and insmod builds a
table of these exported images. Every kernel module must contain module
initialization and module cleanup routines and these symbols are
deliberately not exported but insmod must know the addresses of them so
that it can pass them to the kernel. All being well, insmod is now ready to
initialize the module and it makes a privileged system call passing the kernel
the addresses of the module's initialization and cleanup routines. 
When a new module is added into the kernel, it must update the kernel's set
of symbols and modify the modules that are being used by the new module.
Modules that have other modules dependent on them must maintain a list of
references at the end of their symbol table and pointed at by their module
data structure. Figure  12.1 shows that the VFAT file system module is
dependent on the FAT file system module. So, the FAT module contains a
reference to the VFAT module; the reference was added when the VFAT
module was loaded. The kernel calls the modules initialization routine and, if
it is successful it carries on installing the module. The module's cleanup
routine address is stored in it's module data structure and it will be called
by the kernel when that module is unloaded. Finally, the module's state is
set to RUNNING. 
-->
<p>新しいモジュールもカーネルにシンボルをエクスポートするので、<tt>insmod</tt>
 はエクスポートされるイメージのテーブルを作成しなければならない。すべての
カーネルモジュールには、モジュール初期化と削除のルーチンが含まれていなければ
ならず、それらのシンボルはわざとエクスポートされないのだが、<tt>insmod</tt> 
は、カーネルにそのルーチンのアドレスを渡さなければならないので、それらのアド
レスを知っていなければならない。
これらすべてが上手くいった場合、<tt>insmod</tt> はモジュールを初期化する準備が
整ったため、特権的なシステムコールを発行して、カーネルに対して、モジュールの
初期化ルーチンと削除ルーチンのアドレスを渡す。
<newline>[see: sys_init_module(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/kernel/module.c" 
name="kernel/module.c">]<newline>
新しいモジュールがカーネルに組み込まれるとき、カーネルの一連のシンボルが
更新されなければならず、新規モジュールによって利用されることになるモジュールに
対しても修正が加えられなければならない。
他のモジュールから依存されているモジュールは、そのシンボルテーブルの末尾にある
参照リストを管理しなければならず、その参照リストは自己の <tt><ref 
id="module" name="module"></tt> データ構造体によってポイントされなければなら
ない。
<ref id="figure12-1" name="図表(12.1)">では、VFAT ファイルシステムモジュール
は、FAT ファイルシステムモジュールに依存している。したがって、FAT モジュール
には、VFAT モジュールへの参照が含まれていなければならない。その参照は、VFAT 
モジュールがロードされたときに付け加えられる。
カーネルはモジュール初期化ルーチンを呼び出し、それが成功した場合、モジュールの
インストールを行う。モジュールの削除ルーチンのアドレスは、そのモジュールの 
<tt>module</tt> データ構造体に保存され、モジュールがアンロードされるときに、
カーネルによって呼び出される。最後に、モジュールの状態が RUNNING にセットされ
る。

<!--12.2  Unloading a Module-->
<sect1>モジュールのアンロード<label id="chapter_m_sect2">

<!--
Modules can be removed using the rmmod command but demand loaded
modules are automatically removed from the system by kerneld when they
are no longer being used. Every time its idle timer expires, kerneld makes
a system call requesting that all unused demand loaded modules are
removed from the system. The timer's value is set when you start
kerneld; my kerneld checks every 180 seconds. So, for example, if you
mount an iso9660 CD ROM and your iso9660 filesystem is a loadable
module, then shortly after the CD ROM is unmounted, the iso9660 module
will be removed from the kernel. 
-->
<p>モジュールは <tt>rmmod</tt> コマンドを使って削除することが可能であるが、
オンデマンドでロードされたモジュールは使用されなくなったとき <tt>kerneld
</tt> によって自動的にシステムから削除される。アイドルタイマー(idle timer)が
時間切れになった際はいつも、<tt>kerneld</tt> はシステムコールを発行し、
オンデマンドでロードされたモジュールのなかで使用されなくなったものすべてを
システムから削除するようリクエストする。
タイマーの値は、<tt>kerneld</tt> を始動した時にセットされる。わたしの 
<tt>kerneld</tt> のタイマー設定は 180 秒にしてある。
たとえば、iso9660 CD-ROM をマウントして、その iso9660 ファイルシステムが
ローダブルモジュールであった場合、CD-ROM がアンマウントされてからしばらく
すると、iso9660 モジュールはカーネルから削除される。

<!--
A module cannot be unloaded so long as other components of the kernel are
depending on it. For example, you cannot unload the VFAT module if you
have one or more VFAT file systems mounted. If you look at the output of
lsmod, you will see that each module has a count associated with it. For
example: 
-->
<p>他のカーネルの一部が、あるモジュールに依存している間は、そのモジュールは
アンロードできない。たとえば、ひとつ以上の VFAT ファイルシステムをマウントして
いる場合、VFAT モジュールはアンマウントできない。<tt>lsmod</tt> の出力
を見れば、個々のモジュールが依存関係についてもカウントを持っていることが分か
る。

<verb>
Module:        #pages:  Used by:
msdos              5                  1
vfat               4                  1 (autoclean)
fat                6    &lsqb;vfat msdos&rsqb;  2 (autoclean)
</verb>

<!--
The count is the number of kernel entities that are dependent on this module.
In the above example, the vfat and msdos modules are both dependent on
the fat module and so it has a count of 2. Both the vfat and msdos
modules have 1 dependent, which is a mounted file system. If I were to load
another VFAT file system then the vfat module's count would become 2. A
module's count is held in the first longword of its image. 
-->
<p>カウントは、そのモジュールに依存しているカーネル実体(entity)の数を表してい
る。上記の例では、<tt>vfat</tt> と <tt>msdos</tt> モジュールはどちらも <tt>
fat</tt> モジュールに依存しているので、<tt>fat</tt> のカウントは 2 となって
いる。<tt>vfat</tt> と <tt>msdos</tt> モジュールは両方ともそれに依存する 1 つの
実体を持っているが、その実体とはマウントされたファイルシステムである。
もし、わたしがもうひとつ VFAT ファイルシステムをマウントしたとすると、
<tt>vfat</tt> モジュールのカウントは 2 になるだろう。モジュールのカウントは、
イメージの最初のロングワード(longword)の中に保持されている。

<!--
This field is slightly overloaded as it also holds the AUTOCLEAN and
VISITED flags. Both of these flags are used for demand loaded modules.
These modules are marked as AUTOCLEAN so that the system can
recognize which ones it may automatically unload. The VISITED flag marks
the module as in use by one or more other system components; it is set
whenever another component makes use of the module. Each time the
system is asked by kerneld to remove unused demand loaded modules it
looks through all of the modules in the system for likely candidates. It only
looks at modules marked as AUTOCLEAN and in the state RUNNING. If the
candidate has its VISITED flag cleared then it will remove the module,
otherwise it will clear the VISITED flag and go on to look at the next
module in the system. 
-->
<p>そのフィールドには、AUTOCLEAN と VISITED フラグも保持されるので、やや
情報過多ともいえるフィールドになっている。これらふたつのフラグは、デマンド
ローディングでロードされたモジュールに対して使用される。
そうしたモジュールが AUTOCLEAN とマークされるのは、システムが
そのモジュールを自動的にアンロードする対象と認識できるようにするためである。
VISITED フラグは、ひとつ以上のシステムコンポーネントがそのモジュールを
使っていることを示している。VISITED フラグは、他のコンポーネントがその
モジュールと使うときは必ずセットされる。オンデマンドでロードされたが使用され
なくなったモジュールを削除するかどうかを <tt>kerneld</tt> がシステムに尋ねた
ときは、システムはシステム上のすべてのモジュールを見回して、使用されなくなった
という条件に該当するものを捜す。システムは AUTOCLEAN とマークされていて 
RUNNING 状態にあるモジュールだけを見る。該当するモジュールが VISITED フラグを
クリアした場合、システムはそのモジュールを削除するが、モジュールがフラグをクリ
アしない場合は、システムがその VISITED フラグをクリアして、システム上の次の
モジュールの調査に移る。

<!--
Assuming that a module can be unloaded, its cleanup routine is called to
allow it to free up the kernel resources that it has allocated. 
The module data structure is marked as DELETED and it is unlinked from
the list of kernel modules. Any other modules that it is dependent on have
their reference lists modified so that they no longer have it as a dependent.
All of the kernel memory that the module needed is deallocated. 
-->
<p>モジュールがアンロード可能な場合、そのモジュールの削除ルーチンが呼び出され、
そのルーチンが、モジュールに割り当てられたカーネルリソースを解放する。
<newline>&lsqb;see: sys_delete_module(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/kernel/module.c" 
name="kernel/module.c">&rsqb;<newline>
その <tt><ref id="module" name="module"></tt> データ構造体は DELETED とマーク
され、カーネルモジュールのリストから削除される。(削除されたモジュールが依存
していた)他のモジュールは、削除モジュールがもはや依存するものではなくなった
ので、参照リストを修正しないといけない。
削除モジュールが必要としていたカーネルメモリはすべて割り当てを解放される。