<!--Chapter 3 Memory Management-->
<sect>メモリ管理<label id="chapter_mm">
<p><figure><ph vspace="75"><img src="./The-Linux-Kernel-images/penguin2.gif">
</figure>

<!--
The memory management subsystem is one of the most important parts of the
operating system. Since the early days of computing, there has been a need for
more memory than exists physically in a system. Strategies have been
developed to overcome this limitation and the most successful of these is 
virtual memory. Virtual memory makes the system appear to have more memory 
than it actually has by sharing it between competing processes as they need 
it. 
-->
<p>メモリ管理サブシステムは、オペレーティングシステムの最も重要な部分
のひとつである。コンピュータの黎明期以来、システム上にある物理メモリだけでは
足りない状況がずっと続いてきた。この限界を克服するために様々な戦略が立てられ
たが、それらのうちで最も成功したのが、仮想メモリ(virtual memory)である。
仮想メモリとは、システムに実際以上のメモリがあるかのように見せる仕組みであり、
メモリ争奪関係にあるプロセス間で、必要に応じてそれらを協調して使用することに
より実現されている。

<!--
Virtual memory does more than just make your computer's memory go further.
The memory management subsystem provides: 
-->
<p>仮想メモリは、コンピュータのメモリを大きく見せること以外にも様々な機能を
提供している。メモリ管理サブシステムが提供する機能には、次のようなものがあ
る。

<descrip>

<!--Large Address Spaces-->
<tag>巨大なアドレス空間</tag>
<!--
      The operating system makes the system appear as if it has a larger
      amount of memory than it actually has. The virtual memory can be many
      times larger than the physical memory in the system, 
-->
<p>オペレーティングシステムは、システム上に実際以上のメモリがあるかのように
振る舞う。仮想メモリはシステム上の物理メモリより、何倍も大容量にできる。

<!--Protection-->
<tag>データ保護</tag>
<!--
      Each process in the system has its own virtual address space. These
      virtual address spaces are completely separate from each other and so a
      process running one application cannot affect another. Also, the
      hardware virtual memory mechanisms allow areas of memory to be
      protected against writing. This protects code and data from being
      overwritten by rogue applications. 
-->
<p>システム上のプロセスは、各々が独自の仮想アドレス空間を持っている。これらの
仮想アドレス空間は、お互いに完全に独立しているので、あるアプリケーションを実行
しているプロセスは、他のプロセスに影響を与え得ない。
さらに、メモリエリアはハードウェア上の仮想メモリ機構によって、書き込みから保護
されている。
これによって、コードやデータを、出来の悪いアプリケーションによる上書きから
保護している。

<!--Memory Mapping-->
<tag>メモリマッピング</tag>
<!--
      Memory mapping is used to map image and data files into a processes
      address space. In memory mapping, the contents of a file are linked
      directly into the virtual address space of a process. 
-->
<p>メモリマッピング(memory mapping)は、イメージやデータファイルをプロセスの
アドレス空間にマップ(map)するために使用される。メモリマッピングにおいて、
ファイルの内容は、プロセスの仮想アドレス空間に直接リンクされる。

<!--Fair Physical Memory Allocation-->
<tag>公正な物理メモリの割り当て</tag>
<!--
      The memory management subsystem allows each running process in the
      system a fair share of the physical memory of the system, 
-->
<p>メモリ管理サブシステムによって、システム上で実行されている個々のプロセスは、
システムの物理メモリ上に公正な持ち分を所持することができる。

<!--Shared Virtual Memory-->
<tag>共有仮想メモリ</tag>
<!--
      Although virtual memory allows processes to have separate (virtual)
      address spaces, there are times when you need processes to share
      memory. For example there could be several processes in the system
      running the bash command shell. Rather than have several copies of
      bash, one in each processes virtual address space, it is better to have
      only one copy in physical memory and all of the processes running bash
      share it. Dynamic libraries are another common example of executing
      code shared between several processes. 
-->
<p>仮想メモリはプロセスが個別の(仮想)アドレス空間を持つようにしているが、
複数のプロセスでメモリを共有(share)しなければならない場合もある。たとえば、<tt>
bash</tt> のコマンドシェルを実行しているプロセスがシステム上に複数存在するこ
とがある。その場合、物理メモリ内に複数の <tt>bash</tt> のコピーが存在して、
個々のプロセスが個別の仮想アドレス空間を持つよりも、ひとつだけのコピーが存在
し、<tt>bash</tt> を実行するすべてのプロセスでその仮想アドレス空間を共有する
ほうが効率がよい。動的ライブラリ(dynamic library)は、複数のプロセス間で実行
コードを共有するもうひとつの典型例である。

<!--
      Shared memory can also be used as an Inter Process Communication
      (IPC) mechanism, with two or more processes exchanging information
      via memory common to all of them. Linux supports the Unix TM System
      V shared memory IPC. 
-->
<p>共有メモリ(shared memory)は、プロセス間通信(Inter Process Communication, 
IPC)のメカニズムでも使用される。それは、ふたつ以上のプロセスが、それらすべて
に共通のメモリを経由して、情報を交換する仕組みである。Linux は、Unix System 
V の共有メモリ IPC をサポートしている。


</descrip>


<!--3.1  An Abstract Model of Virtual Memory-->
<sect1>仮想メモリの抽象モデル<label id="chapter_mm_sect1">
<p>

<label id="figure3-1">
<!--Figure 3.1: Abstract model of Virtual to Physical address mapping-->
<#if output="html"><figure>
<ph vspace="100"><img src="./The-Linux-Kernel-images/figure3-1.gif">
</figure>
</#if>
<#unless output="html">
<verb>
                                                             プロセス Y
                                             プロセス Y      +--------+
プロセス X                                  ページテーブル +-| VPFN 7 |
+--------+                                    ________     | |--------|
| VPFN 7 |-+   プロセス X                   +-|_______|<-+ | | VPFN 6 |
|--------| |  ページテーブル                | |_______|  | | |--------|
| VPFN 6 | |   ________                   +-+-|_______|<-+-+ | VPFN 5 |
|--------| +->|_______|-+      +-------+  | | |_______|  |   |--------|
| VPFN 5 |    |_______| |   +->| PFN 4 |<-+-+ |_______|  |   | VPFN 4 |
|--------| +->|_______|-+-+ |  |       |  |   |_______|  |   |--------|
| VPFN 4 | |  |_______| | | |  |-------+  |              |   | VPFN 3 |
|--------| |  |_______| | | |  | PFN 3 |  |              |   |--------|
| VPFN 3 |-+->|_______|-+-+-+  |       |  |              |   | VPFN 2 |
|--------| |            | |    |-------|  |              |   |--------|
| VPFN 2 | |            | |    | PFN 2 |<-+              +---| VPFN 1 |
|--------| |            | |    |       |                     |--------|
| VPFN 1 | |            | |    |-------|                     | VPFN 0 |
|--------| |            | +--->| PFN 1 |                     +--------+
| VPFN 0 |-+            |      |       |
+--------+              |      |-------|
                        +----->| PFN 0 |
                               |       |
                               +-------+
仮想メモリ                     物理メモリ                    仮想メモリ
</verb>
</#if>



<p>図表(3.1) 仮想アドレスから物理アドレスへのマッピングに関する抽象モデル


<!--
Before considering the methods that Linux uses to support virtual memory it is
useful to consider an abstract model that is not cluttered by too much detail. 
-->
<p>Linux が仮想メモリをサポートする方法を考える前に、煩瑣な詳細を省いた抽象
モデルを検討することは有益である。

<!--
As the processor executes a program it reads an instruction from memory and
decodes it. In decoding the instruction it may need to fetch or store the 
contents of a location in memory. The processor then executes the instruction 
and moves onto the next instruction in the program. In this way the processor 
is always accessing memory either to fetch instructions or to fetch and store 
data. 
-->
<p>プロセッサがプログラムを実行するとき、プロセッサはメモリから命令を読み出し
て、デコード(decode)する。命令をデコードする際、プロセッサは、ある地点の
メモリの内容を読み出したり(fetch)、書き込んだり(store)することが必要になる場合
もある。そして、プロセッサはその命令を実行し、プログラムの次の命令に移る。
このように、プロセッサはいつもメモリにアクセスしながら、命令を読み出したり、
あるいは、データを読み書きしたりしている。

<!--
In a virtual memory system all of these addresses are virtual addresses and not
physical addresses. These virtual addresses are converted into physical
addresses by the processor based on information held in a set of tables
maintained by the operating system. 
-->
<p>仮想メモリシステムでは、それらに使用されるアドレスはすべて仮想アドレスで
あり、物理アドレスではない。それらの仮想アドレスはプロセッサによって物理
アドレスに変換されるのだが、その変換は、オペレーティングシステムが管理する
変換テーブルに保持された情報を基にして行われる。

<!--
To make this translation easier, virtual and physical memory are divided into
handy sized chunks called pages. These pages are all the same size, they need
not be but if they were not, the system would be very hard to administer. Linux
on Alpha AXP systems uses 8 Kbyte pages and on Intel x86 systems it uses 4
Kbyte pages. Each of these pages is given a unique number; the page frame
number (PFN). 
-->
<p>この変換を容易にするため、仮想メモリと物理メモリは、ページ(page)と呼ばれる
扱い易い単位に分割されている。それらのページはすべて同じサイズである。ページ
のサイズは必ずしも同一である必要はないのだが、同一サイズでない場合、システム
による管理が非常に困難なものになるためにそうされている。Alpha AXP システム上
の Linux では、8 k バイトのページを使用し、Intel x86 システムでは、4 k バイト
のページが使用されている。ページそれぞれには、他と重複しない数値のページ
フレーム番号(Page Frame Number, PFN)が割り振られている。

<!--
In this paged model, a virtual address is composed of two parts; an offset and
a virtual page frame number. If the page size is 4 Kbytes, bits 11:0 of the 
virtual address contain the offset and bits 12 and above are the virtual page 
frame number. Each time the processor encounters a virtual address it must 
extract the offset and the virtual page frame number. The processor must 
translate the virtual page frame number into a physical one and then access 
the location at the correct offset into that physical page. To do this the 
processor uses page tables. 
-->
<p>このようにページ分割されたシステムの場合、仮想アドレスは、オフセット(offset)
と仮想ページフレーム番号(PFN)のふたつの部分から構成される。ページサイズが 
4 k バイトならば、仮想アドレスの bit 11 から 0 にオフセットが含まれていて、
bit 12 以降が仮想ページフレーム番号となっている。
プロセッサは仮想アドレスに出会うたびに、オフセット番号と仮想ページフレーム
番号を抽出する。プロセッサは、仮想ページフレーム番号を物理ページフレーム番号
に変換し、その上で、該当する物理ページの正しいオフセット番号の位置にアクセス
する。その変換のために、プロセッサはページテーブル(page table)を使用する。

<!--
Figure  3.1 shows the virtual address spaces of two processes, process X and
process Y, each with their own page tables. These page tables map each
processes virtual pages into physical pages in memory. This shows that process
X's virtual page frame number 0 is mapped into memory in physical page frame
number 1 and that process Y's virtual page frame number 1 is mapped into
physical page frame number 4. Each entry in the theoretical page table contains
the following information: 
-->
<p><ref id="figure3-1" name="図表(3.1)">は、プロセス X とプロセス Y というふた
つのプロセスの仮想アドレス空間を示すもので、どちらもプロセス自身のページテー
ブルを持っている。それらのページテーブルは、プロセスの仮想ページをメモリの物理
ページにマップするものである。この図表では、プロセス X の仮想ページフレーム番
号 0 が物理ページフレーム番号 1 にマップされ、プロセス Y の仮想ページフレーム
番号 1 が物理ページフレーム番号 4 にマップされている。理論的には、ページテーブ
ル内のそれぞれのエントリーには、次の情報が含まれている。

<!--
      Valid flag. This indicates if this page table entry is valid, 
      The physical page frame number that this entry is describing, 
      Access control information. This describes how the page may be used.
      Can it be written to? Does it contain executable code? 
-->
<descrip>
<tag>有効フラグ(valid flag)</tag>
ページテーブルのエントリが有効かどうかを示す。

<tag>物理ページフレーム番号(physical page frame number)</tag>
そのエントリが記述している物理ページフレーム番号。

<tag>アクセス制御情報(access control information)</tag>
そのページが利用される方法を記述している。書き込み可能か、
実行コードを含むかといったことに関係する情報。
</descrip>

<!--
The page table is accessed using the virtual page frame number as an offset.
Virtual page frame 5 would be the 6th element of the table (0 is the first
element). 
-->
<p>ページテーブルにアクセスする場合、仮想ページフレーム番号が(ページテーブル
への)オフセットとして使用される。仮想ページフレーム番号の 5 は、ページテーブ
ルの 6 番目の要素に該当する。(0 が最初の要素に該当するためである。)

<!--
To translate a virtual address into a physical one, the processor must first 
work out the virtual addresses page frame number and the offset within that 
virtual page. By making the page size a power of 2 this can be easily done by 
masking and shifting. Looking again at Figures  3.1 and assuming a page size 
of 0x2000 bytes (which is decimal 8192) and an address of 0x2194 in process 
Y's virtual address space then the processor would translate that address into
offset 0x194 into virtual page frame number 1. 
-->
<p>仮想アドレスを物理アドレスに変換する場合、プロセッサはまず仮想アドレスページ
フレーム番号とその仮想ページ内のオフセット値を探さなければならない。ページサ
イズを 2 の n 乗とすることで、マスク操作(masking)とシフト操作(shifting)により
それは簡単に実行できる。もう一度<ref id="figure3-1" name="図表(3.1)">を見てほ
しい。ページサイズが 0x2000 バイト(十進数なら 8192)で、プロセス Y の仮想アド
レス空間でのアドレスが 0x2194 だとすると、プロセッサがそのアドレスを変換した
結果は、オフセット値 0x194 を持つ仮想ページ番号 1 となる。

<!--
The processor uses the virtual page frame number as an index into the
processes page table to retrieve its page table entry. If the page table entry
at that offset is valid, the processor takes the physical page frame number 
from this entry. If the entry is invalid, the process has accessed a 
non-existent area of its virtual memory. In this case, the processor cannot 
resolve the address and must pass control to the operating system so that it 
can fix things up. 
-->
<p>プロセッサは、仮想ページフレーム番号をプロセスのページテーブルへの
インデックスとして使用することで、そのページテーブルエントリを知る。もしその
オフセット位置にあるページテーブルエントリが有効(valid)ならば、プロセッサはその
エントリから物理ページフレーム番号を取得する。エントリが無効なら、プロセスは
物理メモリ上に存在しない仮想メモリ領域にアクセスしたことになる。その場合、
プロセッサはアドレスを解決できないので、オペレーティングシステムに制御を渡す
ことで、問題の解決を依頼する。

<!--
Just how the processor notifies the operating system that the correct process
has attempted to access a virtual address for which there is no valid 
translation is specific to the processor. However the processor delivers it, 
this is known as a page fault and the operating system is notified of the 
faulting virtual address and the reason for the page fault. 
-->
<p>現在のプロセスが有効な変換先のない仮想アドレスにアクセスしようとしたことを
プロセッサがオペレーティングシステムに伝える方法は、プロセッサの種類によって
異なる。しかしプロセッサの伝達方法がどのようなものであれ、その現象
はページフォルト(page fault)と呼ばれていて、オペレーティングシステムには、
フォルトとなった仮想アドレスとフォルトが生じた原因とが通知される。

<!--
Assuming that this is a valid page table entry, the processor takes that 
physical page frame number and multiplies it by the page size to get the 
address of the base of the page in physical memory. Finally, the processor 
adds in the offset to the instruction or data that it needs. 
-->
<p>ページテーブルのエントリが有効であった場合、プロセッサは、物理ページフレーム
番号を取得し、それにページサイズを掛け算して、物理メモリ内のページのベース
アドレス(base address)を取得する。最後に、プロセッサは、(そのベースアドレス
を起点に)取得すべき命令やデータまでのオフセットを、そのベースアドレスに加える
(ことで、完全な物理アドレスを得る)。

<!--
Using the above example again, process Y's virtual page frame number 1 is
mapped to physical page frame number 4 which starts at 0x8000 (4 x 0x2000).
Adding in the 0x194 byte offset gives us a final physical address of 0x8194. 
-->
<p>上記の例を再び取り上げると、プロセス Y の仮想ページフレーム番号 1 は、
物理ページフレーム番号 4 にマップされる。その物理ページフレームは、アドレス 
0x8000(4 x 0x2000)を起点(ベースアドレス)としている。そのアドレスに 0x194 
バイトのオフセット値を加えると、最後に 0x8194 という物理アドレスが得られる。

<!--
By mapping virtual to physical addresses this way, the virtual memory can be
mapped into the system's physical pages in any order. For example, in Figure 
3.1 process X's virtual page frame number 0 is mapped to physical page frame
number 1 whereas virtual page frame number 7 is mapped to physical page frame
number 0 even though it is higher in virtual memory than virtual page frame
number 0. This demonstrates an interesting byproduct of virtual memory; the
pages of virtual memory do not have to be present in physical memory in any
particular order. 
-->
<p>仮想アドレスから物理アドレスへのマッピングにこうした方法を使用することで、
仮想メモリからシステムの物理メモリへのマッピングが、その番号と無関係に可能と
なる。たとえば、<ref id="figure3-1" name="図表(3.1)">において、プロセス X の
仮想ページフレーム番号 0 は、
物理ページフレーム番号 1 にマップされるが、仮想ページフレーム番号 7 は、仮想
ページフレーム 0 より大きな番号であるにも関わらず、物理ページフレーム 0 に
マップされる。このことは、仮想メモリ機構が興味深い副産物を持つことを意味す
る。すなわち、仮想メモリのページは、物理メモリ内で特定の順番通りに並んでいる
必要がないということである。

<!--3.1.1  Demand Paging-->
<sect2>デマンドページング<label id="chapter_mm_sect1-1">

<!--
As there is much less physical memory than virtual memory the operating
system must be careful that it does not use the physical memory inefficiently.
One way to save physical memory is to only load virtual pages that are 
currently being used by the executing program. For example, a database program
may be run to query a database. In this case not all of the database needs to 
be loaded into memory, just those data records that are being examined. If the
database query is a search query then it does not make sense to load the code 
from the database program that deals with adding new records. This technique 
of only loading virtual pages into memory as they are accessed is known as 
demand paging. 
-->
<p>仮想メモリに比べて物理メモリは非常に量が少ないので、オペレーティングシステム
は物理メモリを効率的に使うよう気を配らなければならない。物理メモリを節約す
るひとつの方法は、実行中のプログラムが現在使用している仮想ページだけをロード
することである。たとえば、データベースプログラムがデータベースに問い合わせを
実行したとする。その場合、データベース全体がメモリにロードされる
必要はなく、調べる必要のあるデータレコードだけがロードされればよい。データ
ベースへの問い合わせが検索である場合、新規レコード追加の処理をするデータ
ベースプログラムのコードをロードしても意味がない。アクセスされた仮想ページだけ
をメモリにロードするというこのテクニックは、デマンドページング(demand paging)
と呼ばれる。

<!--
When a process attempts to access a virtual address that is not currently in
memory the processor cannot find a page table entry for the virtual page
referenced. For example, in Figure  3.1 there is no entry in process X's page
table for virtual page frame number 2 and so if process X attempts to read from
an address within virtual page frame number 2 the processor cannot translate
the address into a physical one. At this point the processor notifies the 
operating system that a page fault has occurred. 
-->
<p>プロセスが物理メモリ上にない仮想アドレスにアクセスしようとした場合、プロ
セッサは、参照された仮想ページのページテーブルエントリを見つけることができな
い。たとえば、<ref id="figure3-1" name="図表(3.1)"> では、プロセス X の
ページテーブルには、仮想フレーム番号 2 のエントリがないので、プロセス X が
仮想ページフレーム番号 2 の中にあるアドレスを読もうとしても、プロセッサは、
そのアドレスを物理メモリ上のアドレスに変換できない。この時点で、プロセッサは、
ページフォルトが発生したことをオペレーティングシステムに通知する。

<!--
If the faulting virtual address is invalid this means that the process has
attempted to access a virtual address that it should not have. Maybe the
application has gone wrong in some way, for example writing to random
addresses in memory. In this case the operating system will terminate it,
protecting the other processes in the system from this rogue process. 
-->
<p>フォルトとなった仮想アドレスが無効なものである場合、それはプロセスが存在
しない仮想アドレスにアクセスしようとしたことを意味する。おそらく、アプリ
ケーションに不具合が起こって、たとえばメモリ内のランダムなアドレスへ書き込み
をしようとしたのかもしれない。この場合、オペレーティングシステムはその
プロセスを終了させて、暴走したそのプロセスからシステム内の他のプロセスを
保護する。

<!--
If the faulting virtual address was valid but the page that it refers to is not
currently in memory, the operating system must bring the appropriate page into
memory from the image on disk. Disk access takes a long time, relatively
speaking, and so the process must wait quite a while until the page has been
fetched. If there are other processes that could run then the operating system
will select one of them to run. The fetched page is written into a free 
physical page frame and an entry for the virtual page frame number is added to
the processes page table. The process is then restarted at the machine 
instruction where the memory fault occurred. This time the virtual memory 
access is made, the processor can make the virtual to physical address 
translation and so the process continues to run. 
-->
<p>しかし、フォルトとなった仮想アドレスが有効なものであり、参照されたページは
そのときメモリ内になかっただけである場合、オペレーティングシステムは、ディスク
上のイメージから適切なページをメモリ内に持ってこなければならない。ディスク
アクセスは、相対的に時間の掛かる処理なので、プロセスは、ページが来るまでの間
待っている必要がある。その際に実行可能なプロセスがあれば、オペレーティ
ングシステムはそのいくつかを選んで実行する。そして、取ってきたページを空いた
物理ページフレームに書き込んで、仮想ページフレーム番号用のエントリーを
プロセスのページテーブルに追加する。それによって、プロセスはメモリフォルトが
発生した命令があった場所から再び実行される。今度は、仮想メモリへのアクセスに
成功し、プロセッサも仮想アドレスから物理アドレスへの変換ができるので、
プロセスの実行は継続する。

<!--
Linux uses demand paging to load executable images into a processes virtual
memory. Whenever a command is executed, the file containing it is opened and
its contents are mapped into the processes virtual memory. This is done by
modifying the data structures describing this processes memory map and is
known as memory mapping. However, only the first part of the image is actually
brought into physical memory. The rest of the image is left on disk. As the 
image executes, it generates page faults and Linux uses the processes memory 
map in order to determine which parts of the image to bring into memory for 
execution. 
-->
<p>Linux は、デマンドページングを使用して、実行イメージをプロセスの仮想メモリ
にロードする。コマンドが実行される際はいつも、そのコマンドを含むファイルが
オープンされ、ファイルの内容がプロセスの仮想メモリにマップされる。その処理は、
そのプロセスのメモリマップを記述しているデータ構造体を修正することにより
行われるので、メモリマッピング(memory mapping)と呼ばれる。しかし、実際に物理
メモリに置かれるのはイメージの最初の部分だけであり、残りはディスクに保存され
たままとなる。
したがって、イメージが実行されるとページフォルトが起こり、Linux は、プロセスの
メモリマップを利用して、イメージのどの部分をメモリに持ってくれば実行が完遂でき
るのかを判断する。

<!--3.1.2  Swapping-->
<sect2>スワッピング<label id="chapter_mm_sect1-2">

<!--
If a process needs to bring a virtual page into physical memory and there are 
no free physical pages available, the operating system must make room for this
page by discarding another page from physical memory. 
-->
<p>あるプロセスが仮想ページを物理メモリに持ってこなければならないのだが、利用
可能な物理メモリの空きがない場合、オペレーティングシステムは、別のページを物
理メモリから取り除くことでそのページのための空間を確保しなければならない。

<!--
If the page to be discarded from physical memory came from an image or data
file and has not been written to then the page does not need to be saved. 
Instead it can be discarded and if the process needs that page again it can be
brought back into memory from the image or data file. 
-->
<p>物理メモリから取り除くべきページがイメージやデータファイルのコピーであり、
上書きされてはいない場合、そのページは保存する必要はない。破棄しておいて、プロ
セスが再度そのページを必要としたときに、該当するイメージやデータファイルから
メモリ内に戻せばそれでよい。

<!--
However, if the page has been modified, the operating system must preserve the
contents of that page so that it can be accessed at a later time. This type of
page is known as a dirty page and when it is removed from memory it is saved in
a special sort of file called the swap file. Accesses to the swap file are 
very long relative to the speed of the processor and physical memory and the 
operating system must juggle the need to write pages to disk with the need to 
retain them in memory to be used again. 
-->
<p>しかし、ページが変更されている場合には、オペレーティングシステムは、その
ページを維持して、後でそのページにアクセスできるようにしなければならない。
この種のページは、ダーティページ(dirty page)と呼ばれ、メモリから削除されると
きにスワップファイルと呼ばれる特別なファイルに保存される。スワップファイルへ
のアクセスには、プロセッサとメモリとの間のスピードと比べて非常に長い時間が掛
かるので、オペレーティングシステムは、ページをディスクに書き込む必要がある場合
でも、再使用に備えて出来るだけそれをメモリに保持する必要がある。

<!--
If the algorithm used to decide which pages to discard or swap (the swap
algorithm) is not efficient then a condition known as thrashing occurs. In this
case, pages are constantly being written to disk and then being read back and
the operating system is too busy to allow much real work to be performed. If, 
for example, physical page frame number 1 in Figure  3.1 is being regularly 
accessed then it is not a good candidate for swapping to hard disk. The set of
pages that a process is currently using is called the working set. An 
efficient swap scheme would make sure that all processes have their working 
set in physical memory. 
-->
<p>破棄やスワップするページを決めるために使用されるアルゴリズム(スワップ
アルゴリズム)の効率が悪い場合、スラッシング(thrashing)と呼ばれる状態に陥る。
その場合、ページは間断なくディスクに書き込まれたり読み出されたりするので、
オペレーティングシステムはそれに時間を取られて本来の仕事が出来なくなる。
たとえば、もし物理ページフレーム番号 1 (<ref id="figure3-1" name="図表(3.1)">)
が定期的にアクセスされるなら、
そのページはハードディスクにスワップされるべきではない。プロセスが現在使用し
ているページセットは、ワーキングセット(working set)と呼ばれる。効率の良い
スワップスキームとは、すべてのプロセスが自分のワーキングセットを物理メモリに
持つよう手配するスキームである。

<!--
Linux uses a Least Recently Used (LRU) page aging technique to fairly choose
pages which might be removed from the system. This scheme involves every
page in the system having an age which changes as the page is accessed. The
more that a page is accessed, the younger it is; the less that it is accessed 
the older and more stale it becomes. Old pages are good candidates for 
swapping. 
-->
<p>Linux は、最も使用頻度の少ない(最長時間未使用(Least Recently Used, LRU))
ページの寿命を縮める(エイジング(aging))というテクニックを使って、システム
から削除すべきページを公平に選択している。このスキームでは、システム内のすべ
てのページが寿命(age)を持っていて、それがページアクセスされると、変更される
仕組みになっているいる。
ページへのアクセスが多ければ、そのページの寿命は長くなる。アクセスが少な
ければ寿命が縮み、必要性が薄れる。寿命が尽きたページは、スワッピングの有力な
候補となる。

<!--3.1.3  Shared Virtual Memory-->
<sect2>共有仮想メモリ<label id="chapter_mm_sect1-3">

<!--
Virtual memory makes it easy for several processes to share memory. All
memory access are made via page tables and each process has its own separate
page table. For two processes sharing a physical page of memory, its physical
page frame number must appear in a page table entry in both of their page 
tables.
-->
<p>仮想メモリ機構は、複数のプロセスでのメモリの共有を実現しやすくする。メモリ
へのアクセスはすべてページテーブル経由で行われ、プロセスはそれぞれ自分の独立
したページテーブルを持っている。ふたつのプロセスがメモリ内の物理ページを共有す
るには、その物理ページのフレーム番号が、両者のページテーブル内のエントリに
存在する必要がある。

<!--
Figure  3.1 shows two processes that each share physical page frame number 4.
For process X this is virtual page frame number 4 whereas for process Y this is
virtual page frame number 6. This illustrates an interesting point about 
sharing pages: the shared physical page does not have to exist at the same 
place in virtual memory for any or all of the processes sharing it. 
-->
<p>図表 3.1 では、ふたつのプロセスが物理ページフレーム番号 4 を共有している
様子が示されている。プロセス X にとって、これは仮想ページフレーム番号 4 であ
り、プロセス Y にとって、これは仮想ページ番号 6 である。これはページ共有の
興味深い点を示している。共有された物理ページは、それを共有するプロセスにとって
仮想メモリの同じ位置に存在しなくてもよいということである。

<!--3.1.4  Physical and Virtual Addressing Modes-->
<sect2>物理アドレスモードと仮想アドレスモード<label id="chapter_mm_sect1-4">

<!--
It does not make much sense for the operating system itself to run in virtual
memory. This would be a nightmare situation where the operating system must
maintain page tables for itself. Most multi-purpose processors support the
notion of a physical address mode as well as a virtual address mode. Physical
addressing mode requires no page tables and the processor does not attempt to
perform any address translations in this mode. The Linux kernel is linked to 
run in physical address space. 
-->
<p>オペレーティングシステム自体が仮想メモリ内で実行されるというのはほとんど
ナンセンスである。オペレーティングシステムが自分のページテーブルを管理しなけ
ればならないとしたら、悪夢のような状況になるだろう。大部分の汎用プロセッサ
は、仮想アドレスモードと同時に物理アドレスモードという概念をサポートしてい
る。物理アドレスモードでは、ページテーブルは不要であり、プロセッサはこのモー
ドのときはアドレス変換をしようとしない。Linux カーネルは、この物理アドレス
モードで実行されるようにリンクされている。

<!--
The Alpha AXP processor does not have a special physical addressing mode.
Instead, it divides up the memory space into several areas and designates two 
of them as physically mapped addresses. This kernel address space is known as
KSEG address space and it encompasses all addresses upwards from
0xfffffc0000000000. In order to execute from code linked in KSEG (by 
definition, kernel code) or access data there, the code must be executing in 
kernel mode. The Linux kernel on Alpha is linked to execute from address 
0xfffffc0000310000.
-->
<p>Alpha AXP プロセッサは、特に物理アドレスモードというのは持っていない。
そのかわり、メモリ空間をいくつかのエリアに分割していて、そのうちのふたつを
物理的にマッピングされたアドレス空間として使用する。このカーネルアドレス空間
は、KSEG アドレス空間と呼ばれていて、0xfffffx0000000000 以上のすべてのアドレス
を包含している。KSEG 領域にリンクされているコード(カーネルコードと定義される
コード)を実行したり、その領域のデータにアクセスしたりするためには、そのコード
はカーネルモードで実行される必要がある。Alpha 上の Linux カーネルは、
アドレス 0xfffffc0000310000 から実行されるようにリンクされている。

<!--3.1.5  Access Control-->
<sect2>アクセス制御<label id="chapter_mm_sect1-5">

<!--
The page table entries also contain access control information. As the 
processor is already using the page table entry to map a processes virtual 
address to a physical one, it can easily use the access control information to
check that the process is not accessing memory in a way that it should not. 
-->
<p>ページテーブルのエントリには、アクセス制御情報も含まれている。プロセッサは、
プロセスの仮想アドレスを物理アドレスにマップするためにいつもページテーブルを
使用するので、そこに含まれたアクセス制御情報を利用して、プロセスが許されていな
い方法でメモリにアクセスしていないかどうかを簡単にチェックできる。

<!--
There are many reasons why you would want to restrict access to areas of
memory. Some memory, such as that containing executable code, is naturally
read only memory; the operating system should not allow a process to write data
over its executable code. By contrast, pages containing data can be written to
but attempts to execute that memory as instructions should fail. Most
processors have at least two modes of execution: kernel and user. You would
not want kernel code executing by a user or kernel data structures to be
accessible except when the processor is running in kernel mode. 
-->
<p>メモリの特定のエリアへのアクセスを制限すべき理由は数多くある。実行コードを
含むようなメモリは、通常読み出し専用である。オペレーティングシステムは、プロ
セスがそのような実行コードの位置にデータを上書きするのを許すべきではない。
反対に、データを含むページは上書きされてもよいわけであり、そのメモリの内容を
実行しようとする命令があった場合、失敗させなければならない。
大部分のプロセッサには、実行に関してカーネルモードとユーザモードという少なく
ともふたつのモードがある。カーネルコードをユーザが勝手に実行できないようにする
ためであり、プロセッサがカーネルモードで動いているとき以外は、カーネルのデータ
構造へのアクセスを許さないようにするためである。

<label id="figure3-2">
<!--               Figure 3.2: Alpha AXP Page Table Entry-->
<#if output="html">
<figure><ph vspace="0"><img src="./The-Linux-Kernel-images/figure3-2.gif">
</figure>
</#if>
<#unless output="html">
<verb>
                                   15 13 11
31                                   14 12 10 9 8 7 6 5 4 3 2 1 0
+----------------------------------------------------------------+
|                 | | | |          |  | | |   | | | |  | | | | | |
|                 | | | |          |  |U|K|   |U|K| | G|A|F|F|F|V|
|                 | | | |          |  |W|W|   |R|R| | H|S|O|O|O| |
|                 | | | |          |  |E|E|   |E|E| |  |M|E|W|R| |
|                 | | | |          |  | | |   | | | |  | | | | | |
+----------------------------------------------------------------+
                   ^   ^
                   |   +------- _PAGE_DIRTY
                   |
                   +----------- _PAGE_ACCESSED
63                                                               32
+----------------------------------------------------------------+
|                                                                |
|                                                                |
|                              P F N                             |
|                                                                |
|                                                                |
+----------------------------------------------------------------+
</verb>
</#if>
<p>図表(3.2) Alpha AXP のページテーブルエントリ(PTE)


<!--
The access control information is held in the PTE and is processor specific;
figure  3.2 shows the PTE for Alpha AXP. The bit fields have the following
meanings: 
-->
<p>アクセス制御情報は、PTE に保持されており、それはプロセッサに固有のものであ
る。図表(3.2)は、Alpha AXP の PTE を表している。そのビットフィールドは、次の
ような意味を持つ。

<!--
V     Valid, if set this PTE is valid, 
FOE  ``Fault on Execute'', Whenever an attempt to execute instructions in
      this page occurs, the processor reports a page fault and passes control
      to the operating system, 
FOW ``Fault on Write'', as above but page fault on an attempt to write to this
      page, 
FOR ``Fault on Read'', as above but page fault on an attempt to read from
      this page, 
ASM   Address Space Match. This is used when the operating system wishes
      to clear only some of the entries from the Translation Buffer, 
KRE   Code running in kernel mode can read this page, 
URE   Code running in user mode can read this page, 
GH    Granularity hint used when mapping an entire block with a single
      Translation Buffer entry rather than many, 
KWE   Code running in kernel mode can write to this page, 
UWE   Code running in user mode can write to this page, 
page frame number
      For PTEs with the V bit set, this field contains the physical Page Frame
      Number (page frame number) for this PTE. For invalid PTEs, if this field
      is not zero, it contains information about where the page is in the swap
      file. 
-->
<label id="chapter_mm_pfn">
<verb>
V     「有効(Valid)」。これが設定されると、PTE が有効となる。
FOE   「実行フォールト(Fault On Execute)」。このページ内で命令が実行されようとし
      た際は、プロセッサがページフォルトを報告し、制御をオペレーティングシステム
      に渡す。
FOW   「書き込みフォールト(Fault on Write)」。上記と同様だが、このページへ書き込
      もうとした場合のページフォルトである。
FOR   「読み込みフォールト(Fault On Read)」。上記と同様だが、このページの読み込も
      うとした場合のページフォルトである。
ASM   「アドレス空間合致(Address Space Match)」。これが使用されるのは、オペレー
       ティングシステムが変換テープルから数個のエントリだけを削除したいときである。
KRE    カーネルモードで実行されているコードは、このページを読むことができる。
URE    ユーザモードで実行されているコードは、このページを読むことができる。
GH     Granularity hint(粒度ヒント). ひとつのブロック全体を分割せずに単一の変換
       バッファにマッピングするときに利用される。
KWE    カーネルモードで実行されているコードはこのページに書き込み可能。
UWE    ユーザモードで実行されているコードは、このページに書き込み可能。
PFN(page frame number)
       V ビットが設定された PTE では、このフィールドには、当該 PTE への物理フレー
       ム番号(ページフレーム番号)が書かれている。V ビットが設定されていおらず、こ
       のフィールドがゼロでない場合、スワップファイル内でのページの場所に関する情
       報が書かれている。
</verb>
<!--
The following two bits are defined and used by Linux: 
-->
<p>次のふたつのビットは、Linux で定義され、使用されているものである。

<!--
_PAGE_DIRTY
      if set, the page needs to be written out to the swap file, 
_PAGE_ACCESSED
      Used by Linux to mark a page as having been accessed. 
-->
<verb>
_PAGE_DIRTY
      これが設定された場合、このページはスワップに書き出される必要がある。
_PAGE_ACCESSED
      ページがアクセスされたことを記すために使用される。
</verb>

<!--3.2  Caches-->
<sect1>キャッシュ<label id="chapter_mm_sect2">

<!--
If you were to implement a system using the above theoretical model then it
would work, but not particularly efficiently. Both operating system and 
processor designers try hard to extract more performance from the system. 
Apart from making the processors, memory and so on faster the best approach is
to maintain caches of useful information and data that make some operations
faster. Linux uses a number of memory management related caches: 
-->
<p>上記の理論モデルを使ってシステムを実装した場合、確かに機能はするであろうが、
それほど効率のよいものにはならない。オペレーティングシステムとプロセッサの
設計者はどちらもシステムからよりよいパフォーマンスを引き出そうと懸命に努力
しているからである。より速いプロセッサやメモリを製造するといったことを別に
すると、処理速度を上げる最良の方法は、頻繁に使用する情報やデータのキャッシュ
を維持管理することである。Linux では、キャッシュに関するいくつかのメモリ管理
機構が利用されている。

<descrip>
<!--Buffer Cache-->
<tag>バッファキャッシュ</tag>
<!--
      The buffer cache contains data buffers that are used by the block device
      drivers. 
      These buffers are of fixed sizes (for example 512 bytes) and contain
      blocks of information that have either been read from a block device or
      are being written to it. A block device is one that can only be accessed
      by reading and writing fixed sized blocks of data. All hard disks are
      block devices. 
-->
<p>バッファキャッシュ(buffer cache)には、ブロックデバイスドライバが使用する
データバッファが含まれている。
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/fs/buffer.c" 
name="fs/buffer.c">]<newline>
これらのバッファは固定サイズ(たとえば、512 バイト)で、ブロックデバイスから
読み出されたか、そこに書き込まれた情報のブロックが入っている。ブ
ロックデバイスとは、データアクセスの際に、固定サイズのブロック単位でのみ読み
書きできるデバイスを指す。すべてのハードディスクはブロックデバイスである。

<!--
      The buffer cache is indexed via the device identifier and the desired
      block number and is used to quickly find a block of data. Block devices
      are only ever accessed via the buffer cache. If data can be found in the
      buffer cache then it does not need to be read from the physical block
      device, for example a hard disk, and access to it is much faster. 
-->
<p>バッファキャッシュは、デバイス識別子と必要なブロック番号とでインデックス付け
されていて、データブロックをすばやく見つけだすために使用されるものである。
ブロックデバイスは、バッファキャッシュを経由しなければアクセスできない。
データがバッファキャッシュに見つかれば、たとえばハードディスクのような物理
ブロックデバイスから読み出す必要がなくなるので、アクセスがずっと高速になる。

<!--Page Cache-->
<tag>ページキャッシュ</tag>

<!--
      This is used to speed up access to images and data on disk. 
      It is used to cache the logical contents of a file a page at a time and 
      is accessed via the file and offset within the file. As pages are read 
      into memory from disk, they are cached in the page cache. 
-->
<p>ページキャッシュ(page cache)は、ディスク上のイメージやデータへのアクセスを
高速化するために使用される。
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/filemap.c" 
name="mm/filemap.c">]<newline>
これは、ページ単位でファイルの論理的な内容をキャッシュし、ファイル名と
そのファイル内のオフセットを使ってアクセスされる。ページがディスクからメモリ
に読み出されると、それらはページキャッシュにキャッシュされる。

<!--Swap Cache-->
<tag>スワップキャッシュ</tag>

<!--
Only modified (or dirty) pages are saved in the swap file. 
So long as these pages are not modified after they have been written to
the swap file then the next time the page is swapped out there is no need
to write it to the swap file as the page is already in the swap file. 
Instead the page can simply be discarded. In a heavily swapping system 
this saves many unnecessary and costly disk operations. 
-->
<p>変更された(あるいは、dirty な)ページだけが、スワップファイルに保存される。
<newline>[see: swap.h, <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/swap_state.c" 
name="mm/swap_state.c">, <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/swapfile.c" 
name="mm/swapfile.c">]<newline>
当該ページがスワップファイルに書き込まれてから変更されていない場合は、再度
スワップアウトされたとしても、同じページがすでにスワップファイル内にあるわけ
だから、スワップファイルに書き込む必要はない。そのページは単に破棄される。
システムがスワップを頻繁に使用する場合、これによって時間の掛かる不必要な
ディスク操作を大幅に省略できる。

<!--Hardware Caches-->
<tag>ハードウェアキャッシュ</tag>

<!--
      One commonly implemented hardware cache is in the processor; a cache
      of Page Table Entries. In this case, the processor does not always read
      the page table directly but instead caches translations for pages as it
      needs them. These are the Translation Look-aside Buffers and contain
      cached copies of the page table entries from one or more processes in
      the system. 
-->
<p>ハードウェアキャッシュ(hardware cache)の実装として一般的なのが、プロセッサ
内のハードウェアキャッシュである、ページテーブルエントリのキャッシュである。
この場合、プロセッサはいつも直接ページテーブルを読み出すのではなく、変換が
必要であったときにそのページ変換をキャッシュしておく。プロセッサ内には、
アドレス変換バッファ(Translation Look-aside Buffer, TLB)があり、そこには、
システム上の複数のプロセスに関するページテーブルエントリのコピーがキャッシュ
されている。

<!--
      When the reference to the virtual address is made, the processor will
      attempt to find a matching TLB entry. If it finds one, it can directly
      translate the virtual address into a physical one and perform the correct
      operation on the data. If the processor cannot find a matching TLB entry
      then it must get the operating system to help. It does this by signalling
      the operating system that a TLB miss has occurred. A system specific
      mechanism is used to deliver that exception to the operating system
      code that can fix things up. The operating system generates a new TLB
      entry for the address mapping. When the exception has been cleared, the
      processor will make another attempt to translate the virtual address.
      This time it will work because there is now a valid entry in the TLB for
      that address. 
-->
<p>仮想アドレスへの参照が行われるとき、プロセッサは合致する TLB エントリを
探そうとする。それが見つかれば、仮想アドレスを直接物理アドレスに変換して、
データに対して適切な処理を実行する。プロセッサが合致する TLB エントリを見つけ
出せない場合は、オペレーティングシステムに助けを求める。すなわち、プロセッサ
は、オペレーティングシステムに対して、TLB 失敗(TLB miss)が起こったことをシグ
ナルで伝える。システム固有のメカニズムを使用して、その例外(exception)をオペ
レーティングシステムの例外処理コードに渡す。オペレーティングシステムは、その
シグナルを受けて、アドレスマッピングのための新しい TLB エントリを生成する。
例外がクリアされると、プロセッサは再度仮想アドレスの変換を試みる。今回は、
TLB 内に必要なアドレスに関する有効なエントリがあるので、問題なく変換される。 

</descrip>

<!--
The drawback of using caches, hardware or otherwise, is that in order to save
effort Linux must use more time and space maintaining these caches and, if the
caches become corrupted, the system will crash. 
-->
<p>ハードウェアキャッシュやその他のキャッシュを使う場合の欠点は、手順を簡略化
するために、これまで以上の時間とメモリ空間を使ってそうしたキャッシュを維持し
なければならないということであり、もしキャッシュが壊れると、システムがクラッ
シュするということである。

<!--3.3  Linux Page Tables-->
<sect1>Linux のページテーブル<label id="chapter_mm_sect3">
<p>

<!--                 Figure 3.3: Three Level Page Tables-->
<#if output="html">
<figure><ph vspace="1"><img src="./The-Linux-Kernel-images/figure3-3.gif">
</figure>
</#if>
<#unless output="html">
<verb>
                         仮想アドレス
+-------+--------------+-------------+-----------+----------------+
|       |              |             |           |                |
|       |   Level 1    |  Level 2    |  Level 3  |Byte within page|
|       |      |       |     |       |     |     |         |      |
+-------+------+-------+-----+-------+-----+-----+---------+------+
               |             |             |               |
               |             |             |               |
    Level 1    |  Level 2    |  Level 3    |               |
    Page Table |  Page Table |  Page Table | Physical Page |
    +-------+  |  +-------+  |  +-------+  |  +---------+  |
    |       |  |  |       |  |  |       |  |  |         |  |
    |       |  |  |       |  |  |       |  |  |         |  |
    |---+---|  |  |---+---|  |  |---+---+  |  |---------|  |
    |PFN|   |<-+  |PFN|   |<-+  |PFN|   |<-+  |         |<-+
    |-+-+---|     |-+-+---|     |-+-+---|     |---------|
    | |     |     |  |    |     | |     |     |         |
PGD | |     |     |  |    |     | |     |     |         |
--->+-+-----+  +->+--+----+  +->+-+-----+  +->+---------+
      |        |     |       |    |        |
      +--------+     +-------+    +--------+
</verb>
</#if>
<p>図表(3.3) 3 つのレベルのページテーブル


<!--
Linux assumes that there are three levels of page tables. Each Page Table
accessed contains the page frame number of the next level of Page Table. Figure
  3.3 shows how a virtual address can be broken into a number of fields; each
field providing an offset into a particular Page Table. To translate a virtual
address into a physical one, the processor must take the contents of each level
field, convert it into an offset into the physical page containing the Page 
Table and read the page frame number of the next level of Page Table. This is 
repeated three times until the page frame number of the physical page 
containing the virtual address is found. Now the final field in the virtual 
address, the byte offset, is used to find the data inside the page. 
-->
<p>Linux では、3 つのレベルのページテーブルの存在が前提になっている。アクセス
される個々のページテーブルには、次の段階のページテーブルにおけるページ
フレーム番号が含まれている。図表(3.3)では、仮想アドレスがいくつかのフィールド
に分割されている様子が示されている。図中の仮想アドレスの個々のフィールドが
提供するのは、特定のページテーブルへのオフセットである。プロセッサは、
仮想アドレスを物理アドレスに変換するため、まず個々のレベルのフィールドの
内容を取得して、その内容を当該レベルのページテーブルを含む物理ページ上での
オフセットへと変換し、それによって次のレベルのページテーブルのページフレーム
番号を読み取る。この処理を三度繰り返すと、その仮想アドレスを含んだ物理ページ
のページフレーム番号が分かる。仮想アドレスの最後のフィールドは、バイト
オフセット(byte offset)となっていて、それを使用して当該物理ページ内で必要な
データを見つけ出す。

<!--
Each platform that Linux runs on must provide translation macros that allow the
kernel to traverse the page tables for a particular process. This way, the 
kernel does not need to know the format of the page table entries or how they 
are arranged. 
This is so successful that Linux uses the same page table manipulation code for
the Alpha processor, which has three levels of page tables, and for Intel x86
processors, which have two levels of page tables. 
-->
<p>Linux を実行するプラットフォームが提供しなければならないのが、変換マクロ
である。これは、カーネルが特定のプロセスのためにページテーブルを走査すること
を可能にするものである。そうすることで、カーネルはページテーブルエントリの
フォーマットや、その仕組みを知る必要がなくなる。
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/include/asm-i386/pgtable.h" 
name="include/asm/pgtable.h">]<newline>
この方法は非常に成功しているので、Linux は、ページテーブル操作のコードとして
 Alpha プロセッサにも Intel x86 プロセッサにも同じものを使用している。ただ、
Alpha プロセッサは、3 つのレベルのページテーブルを持つが、Intel x86 は、
2 つのレベルのページテーブルを持つという違いがある。

<!--3.4  Page Allocation and Deallocation-->
<sect1>ページの割り当てとページの解放<label id="chapter_mm_sect4">

<!--
There are many demands on the physical pages in the system. For example,
when an image is loaded into memory the operating system needs to allocate
pages. These will be freed when the image has finished executing and is
unloaded. Another use for physical pages is to hold kernel specific data
structures such as the page tables themselves. The mechanisms and data
structures used for page allocation and deallocation are perhaps the most 
critical in maintaining the efficiency of the virtual memory subsystem. 
-->
<p>システム内の物理メモリに対する需要は大きい。たとえば、イメージがメモリに
ロードされるとき、オペレーティングシステムは、それに物理ページを割り当てる。
イメージが実行を終了し取り除かれたら、そのページは解放される。物理メモリは他
にも、ページテーブル自体のようなカーネル固有のデータ構造を保持する用途に使用
される。ページ割り当てと解放に使用されるメカニズムとデータ構造は、仮想メモリ
サブシステムの効率を維持する上でおそらく最も重要なものである。

<!--
All of the physical pages in the system are described by the mem_map data
structure which is a list of mem_map_t (footnote 1) structures which is 
initialized at boot time. Each mem_map_t describes a single physical page in 
the system. Important fields (so far as memory management is concerned) are: 
-->
<p>システム内のすべての物理ページは <tt><ref id="mem_map_t" 
name="mem_map"></tt> というデータ構造に
よって記述されている。それは、<tt><ref id="mem_map_t" name="mem_map_t"></tt> 
構造体(<ref id="chapter_mm_fn1" name="脚注 1 ">)の
リストであり、それらは起動時に初期化される。
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/include/linux/mm.h" 
name="include/linux/mm.h">]<newline>
個々の <tt>mem_map_t</tt> は、システム内の単一の物理ページを記述する。(メモリ
管理に関する限り)その構造体の重要なフィールドには、次のようなものがある。

<!--
count This is a count of the number of users of this page. The count is greater
      than one when the page is shared between many processes, 
age This field describes the age of the page and is used to decide if the page
      is a good candidate for discarding or swapping, 
map_nr This is the physical page frame number that this mem_map_t describes.
-->
<verb>
count   これは、そのページのユーザ数のカウンターである。ページが複数のプロセ
        スで共有されている時、このカウントは 1 より多くなる。
age     このフィールドは、ページの 寿命(age)を記述するもので、そのページが破棄
        やスワップの候補であるかを判断するのに使われる。
map_nr  これは、mem_map_t が記述する物理ページのフレーム番号である。
</verb>

<!--
The free_area vector is used by the page allocation code to find and free
pages. The whole buffer management scheme is supported by this mechanism
and so far as the code is concerned, the size of the page and physical paging
mechanisms used by the processor are irrelevant. 
-->
<p><tt><ref id="free_area" name="free_area"></tt> という配列も、ページ割り当
てのコードにより、ページの検索と解放のために使用される。すべてのバッファ管理
スキームはこのメカニズムによってサポートされており、そのコードに関する限り、
プロセッサの物理ページングメカニズムとページサイズとの間には、関連性がない。

<!--
Each element of free_area contains information about blocks of pages. The
first element in the array describes single pages, the next blocks of 2 pages,
the next blocks of 4 pages and so on upwards in powers of two. The list element
is used as a queue head and has pointers to the page data structures in the
mem_map array. Free blocks of pages are queued here. map is a pointer to a
bitmap which keeps track of allocated groups of pages of this size. Bit N of 
the bitmap is set if the Nth block of pages is free. 
-->
<p><tt><ref id="free_area" name="free_area"></tt> の個々の要素は、ブロック単位
のページに関する情報を含んでいる。
すなわち、配列の最初の要素はひとつのページ、次が 2 つのページから成るブロック、
さらに次が 4 つのページから成るブロックというふうに 2 の n 乗でブロックのページ
数が増える。
構造体の要素 <tt><ref id="free_area" name="list"></tt> はキューの先頭として
使用され、<tt><ref id="mem_map_t" name="mem_map"></tt> 配列内の <tt><ref 
id="mem_map_t" name="page"></tt> データ構造体へのポインタとなっている。
(訳注: <tt>list</tt> は、v2.0.12 以降は、<tt>next</tt> と <tt>prev</tt> による
二重連結リストになっています。)
空のページブロックはこのキューに並べられる。<tt><ref id="free_area" 
name="map"></tt> は個々のサイズのページグループの割り当て状態を管理してい
るビットマップ(bitmap)に対するポインタである。bitmap の N ビット目は、ページの 
N 番目のブロックが空である場合にセットされる。

<!--
Figure  free-area-figure shows the free_area structure. Element 0 has one
free page (page frame number 0) and element 2 has 2 free blocks of 4 pages, the
first starting at page frame number 4 and the second at page frame number 56. 
-->
<p><ref id="figure3-4" name="図表(3.4)">では、<tt>free_area</tt> 構造体が示
されている。
要素 0 はひとつの空ページ(ページフレーム番号 0 )を持っており、要素 2 は 4 
つのページから成る 2 つの空ブロックを持っている。最初の空ブロックは、ページ
フレーム番号 4 から始まり、次の空ブロックはページフレーム番号 56 から始まって
いる。

<!--3.4.1  Page Allocation-->
<sect2>ページの割り当て<label id="chapter_mm_sect4-1">
<p>
<!--
Linux uses the Buddy algorithm (footnote 2) to effectively allocate and 
deallocate blocks of pages. The page allocation code attempts to allocate a 
block of one or more physical pages. Pages are allocated
in blocks which are powers of 2 in size. That means that it can allocate a 
block 1 page, 2 pages, 4 pages and so on. So long as there are enough free 
pages in the system to grant this request (nr_free_pages > min_free_pages) the
allocation code will search the free_area for a block of pages of the size 
requested. Each element of the free_area has a map of the allocated and free 
blocks of pages for that sized block. For example, element 2 of the array has 
a memory map that describes free and allocated blocks each of 4 pages long. 
-->
<p>Linux は、相棒アルゴリズム
(<ref id="buddy_algorithm" name="Buddy algorithm">)
<ref id="chapter_mm_fn1" name="(脚注 2)"> 
を使用することで、ページブロックを効率的に割り当てたり解放したりしている。
<newline>[see: __get_free_page(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/page_alloc.c" 
name="mm/linux/page_alloc.c">]<newline>
ページ割り当てのコードは、ひとつもしくは複数のページから成るブロックを割り当
てようとする。ページの割り当ては、大きさとして 2 の n 乗のブロック単位となって
いる。すなわち、ひとつのブロックに 1 つのページ、2 つのページ、4 つのページ等が
割り当てられる。システム内に要求(nr_free_pages &gt; 
min_free_pages)に応えられるだけの空き空間があれば、割り当て
コードは、要求されたサイズのページ数でブロックを作成するために <tt>
<ref id="free_area" name="free_area"></tt> を調べる。
<tt>free_area</tt> のそれぞれの要素は、該当するサイズのブロックに関するマップ
を持っていて、割り当て済みもしくは空いているページブロックが参照できるように
なっている。たとえば、配列の要素 2 が持つメモリマップでは、4 つのページから成る
それぞれのブロックのどれが割り当て済みであり、どれが空なのかが記録されている。

<!--
The allocation algorithm first searches for blocks of pages of the size 
requested. It follows the chain of free pages that is queued on the list 
element of the free_area data structure. If no blocks of pages of the 
requested size are free, blocks of the next size (which is twice that of the 
size requested) are looked for. This process continues until all of the 
free_area has been searched or until a block of pages has been found. If the 
block of pages found is larger than that requested it must be broken down 
until there is a block of the right size. Because the blocks are each a power 
of 2 pages big then this breaking down process is easy as you simply break the
blocks in half. The free blocks are queued on the appropriate queue and the 
allocated block of pages is returned to the caller. 
-->
<p>割り当てアルゴリズムは、まず要求されたサイズのページブロックを探す。それは、
<tt><ref id="free_area" name="free_area"></tt> データ構造体のキューにある、
<tt><ref id="free_area" name="list"></tt> 要素上から、空のページの連続を調
べる。もし要求されたサイズのページブロックでは空きがない場合、
次のサイズ(これは要求されたサイズの 2 倍である)のブロックがないか調査する。
この過程は、<tt>free_area</tt> のすべてが調べられるか、ページブロックが見つかる
かするまで続けられる。見つかったページブロックが当初の要求よりも大きい場合、
適切なサイズになるまで分割される。ブロックは 2 の n 乗のページから成り立つの
で、この分割プロセスは半分に割るだけの簡単なものである。空ブロックは適当な
キュー上に並べられ、割り当てられるページブロックが、呼び出しをしたプロセスに
返される。

<label id="figure3-4">
<!--              Figure 3.4: The free_area data structure-->
<#if output="html">
<figure><ph vspace="1"><img src="./The-Linux-Kernel-images/figure3-4.gif">
</figure>
</#if>
<#unless output="html">
<verb>

                      free_area                 物理メモリ
                       +-----+                 +-----------+
                       |     |                 |           |
                       |  5  |                 |           |
                       |-----|                 |-----------|
                       |     |                 |           |8
                       |  4  |      map        |           | 
                       |-----|    +------+     |-----------|
                       |     |--->+------+     | / / / /   |7
mem_map_t  mem_map_t   |  3  |      map        |  / / / /  |
 +----+     +----+     |-----|    +------+     |-----------|
 |    |<----|    |<----|     |--->|      |     | / / / /   |6
 |    |---->|    |---->|  2  |    +------+     |  / / / /  |
 | 56 |     |  4 |     |-----|      map        |-----------|
 +----+     +----+     |     |--->+------+     | / / / /   |5
           mem_map_t   |  1  |    |      |     |  / / / /  |
            +----+     |-----|    |      |     |-----------|
            |    |<----|     |    +------+     | / / / /   |4
            |    |---->|  0  |-+    map        |  / / / /  |
            |  0 |     +-----+ |  +------+     |-----------|
            +----+             +->|      |     |           |3
                                  |      |     |           |
                                  |      |     |-----------|
                                  |      |     |           |2
                                  |      |     |           |
                                  +------+     |-----------|   *
                                               |           |1 /| 
                                               |           |   |
                                               |-----------|   |
                            / / / /            | / / / /   |0 PFN
                             / / / / Free PFN  |  / / / /  |
                                               +-----------+
</verb>
</#if>
<p>図表(3.4) free_area のデータ構造

<!--
For example, in Figure  3.4 if a block of 2 pages was requested, the first 
block of 4 pages (starting at page frame number 4) would be broken into two 2 
page blocks. The first, starting at page frame number 4 would be returned to 
the caller as the allocated pages and the second block, starting at page frame
number 6 would be queued as a free block of 2 pages onto element 1 of the 
free_area array. 
-->
<p>たとえば、図表(3.4)では、2 つのページから成るブロックが要求された場合、
(ページフレーム番号 4 から始まっている) 4 つのページから成る最初のブロック
が、2 つのページから成るふたつのブロックに分割される。ページフレーム番号 4 
から始まる最初のブロックは、割り当てられたページとして呼び出したプロセスに
戻され、ページフレーム番号 6 から始まる二番目のブロックは、<tt><ref 
id="free_area" name="free_area"></tt> 配列の要素 1 上にある 2 つのページから
成る空ブロックとしてキュー上に置かれる。

<!--3.4.2  Page Deallocation-->
<sect2>ページの解放<label id="chapter_mm_sect4-2">
<p>
<!--
Allocating blocks of pages tends to fragment memory with larger blocks of free
pages being broken down into smaller ones. The page deallocation code 
recombines pages into larger blocks of free pages whenever it can. In fact the
page block size is important as it allows for easy combination of blocks into
larger blocks. 
-->
<p>ページブロックの割り付けは、大きな空ページを小さく分割するので、
断片化したメモリ(framgment memory)を生じやすい。
<newline>[see: free_pages(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/page_alloc.c" 
name="mm/page_alloc.c">]<newline>
ページを解放するコード(page deallocation code)は、
可能なときはいつでも、空のページをより大きなブロックに連結する。実際、
ブロックをまとめてより大きなブロックを簡単に作れることを考えると、
この(2 の n 乗という)ページブロックサイズには重要な意味がある。

<!--
Whenever a block of pages is freed, the adjacent or buddy block of the same
size is checked to see if it is free. If it is, then it is combined with the 
newly freed block of pages to form a new free block of pages for the next size
block of pages. Each time two blocks of pages are recombined into a bigger 
block of free pages the page deallocation code attempts to recombine that 
block into a yet larger one. In this way the blocks of free pages are as large
as memory usage will allow. 
-->
<p>ページブロックが解放されると、同じサイズの近接ブロックもしくは相棒(buddy)
ブロックが空かどうかチェックされる。もしそうなら、新しく解放されたページ
ブロックと結合して、一段階大きいサイズの新しい空ブロックを作成する。ふたつの
ページブロックが結合されてより大きな空のページブロックが形成されるたびに、
ページ解放コードは、そのブロックをさらに大きなものにしようとする。このように
して、空のページブロックは、メモリの使用方法として許される限り大きなブロックに
なっていく。

<!--
For example, in Figure  3.4, if page frame number 1 were to be freed, then that
would be combined with the already free page frame number 0 and queued onto
element 1 of the free_area as a free block of size 2 pages. 
-->
<p>たとえば、<ref id="figure3-4" name="図表(3.4)">では、ページフレーム番号 1 が
解放されると、すでに解放されていたページフレーム番号 0 と結合される。そして、
2 つのページから成る空ブロックとして <tt><ref id="free_area" name="free_area">
</tt> の要素 1 上のキューに置かれる。


<!--3.5  Memory Mapping-->
<sect1>メモリマッピング<label id="chapter_mm_sect5">

<!--
When an image is executed, the contents of the executable image must be
brought into the processes virtual address space. The same is also true of any
shared libraries that the executable image has been linked to use. The
executable file is not actually brought into physical memory, instead it is 
merely linked into the processes virtual memory. Then, as the parts of the 
program are referenced by the running application, the image is brought into 
memory from the executable image. This linking of an image into a processes 
virtual address space is known as memory mapping. 
-->
<p>イメージが実行されるとき、その実行イメージの内容は、プロセスの仮想アドレス
空間に置かれなければならない。このことは、実行イメージで使用するためにリンク
された共有ライブラリの場合でも同じである。実行ファイルは実際に物理
メモリに置かれるわけではなく、プロセスの仮想メモリにリンクされるだけである。
そして、実行中のアプリケーションからそのプログラムの一部が参照されると、実行
イメージ内のその部分のイメージがメモリの中に置かれる。あるイメージを、プロセ
スの仮想アドレス空間にリンクさせるこの仕組みは、メモリマッピング
(memory mapping)と呼ばれる。

<label id="figure3-5">
<!--                Figure 3.5: Areas of Virtual Memory-->
<#if output="html">
<figure><ph vspace="100"><img src="./The-Linux-Kernel-images/figure3-5.gif">
</figure>
</#if>
<#unless output="html">
<verb>
                                              +--------------+
                                              |              |
                                              |              |
                                              |              |
                                      +------>|--------------|
                                      |       |              |
                                      |       |              |
                                      |       |              |
                                      |       | Virtual Area |
vm_area_struct                        |       |              |
+------------+                        |       |              |
|  vm_end    |------------------------+       |              |
|------------|                                |              |
|  vm_start  |------------------------------->|--------------|
|------------|                                |              |
|  vm_flags  |                                |              |
|----------  |                                |              |
|  vm_inode  |                                |              |
|------------|            仮想メモリ          |              |
|  vm_ops    |----------> 操作ルーチン        |              |
|------------|                                |              |
|            |              open()            |              |
|            |              close()           |              |
|------------|              unmap()           |              |
|  vm_next   |              protect()         |              |
+------------+              advise()          |              |
                            nopage()          |              |
                            wppage()          |              |
                            swapout()         |              |
                            swapin()          |              |
                                              +--------------+
</verb>
</#if>
<p>図表3.5 仮想メモリのエリア


<!--
Every processes virtual memory is represented by an mm_struct data
structure. This contains information about the image that it is currently
executing (for example bash) and also has pointers to a number of
vm_area_struct data structures. Each vm_area_struct data structure
describes the start and end of the area of virtual memory, the processes access
rights to that memory and a set of operations for that memory. These operations
are a set of routines that Linux must use when manipulating this area of 
virtual memory. For example, one of the virtual memory operations performs the
correct actions when the process has attempted to access this virtual memory 
but finds (via a page fault) that the memory is not actually in physical 
memory. This operation is the nopage operation. The nopage operation is used 
when Linux demand pages the pages of an executable image into memory. 
-->
<p>すべてのプロセス仮想メモリは、<tt><ref id="mm_struct" name="mm_struct">
</tt>データ構造体で表現される。これには、現在実行中のイメージ(たとえば、
<tt>bash</tt>)に関する情報が含まれると同時に、
いくつかの <tt><ref id="vm_area_struct" name="vm_area_struct"></tt> データ
構造体へのポインタも含まれる。
<tt>vm_area_struct</tt> データ構造体には、その仮想メモリ領域の始点と終点、
そのメモリへのプロセスのアクセス権、およびそのメモリに対する一連の操作ルーチン
が含まれている。これらの操作ルーチンは、Linux がこの仮想メモリの領域を操作する
際に使わなければならない一連のルーチンである。たとえば、仮想メモリ操作のひと
つに訂正処理があり、それはプロセスが仮想メモリにアクセスしようとしたが、
(ページフォルトによって)その仮想メモリが実際には物理メモリ上にないことが分
かった時になされる。この操作は、<tt><ref id="vm_operations_struct" 
name="nopage"></tt> 操作である。
<tt>nopage</tt> 操作が利用されるのは、Linux のデマンドページングにより実行
イメージのページが物理メモリ内にページを割り当てられるときである。

<!--
When an executable image is mapped into a processes virtual address a set of
vm_area_struct data structures is generated. Each vm_area_struct data
structure represents a part of the executable image; the executable code,
initialized data (variables), unitialized data and so on. Linux supports a 
number of standard virtual memory operations and as the vm_area_struct data
structures are created, the correct set of virtual memory operations are
associated with them. 
-->
<p>実行イメージがプロセス仮想アドレスにマップされるとき、<tt><ref 
id="vm_area_struct" name="vm_area_struct"></tt> データ構造が一組生成される。
<tt>vm_area_struct</tt> データ構造体はそれぞれ実行イメージの一部を表している。
実行コード、初期化されたデータ(変数)、初期化されないデータ等につき、ひとつづつ
の構造体が生成される。Linux はいつくかの標準的な仮想メモリ操作をサポートしてい
るので、<tt>vm_area_struct</tt> データ構造体が生成されると、仮想メモリ操作の
適切なセットがそれらと結びつけられる。

<!--3.6  Demand Paging-->
<sect1>デマンドページング<label id="chapter_mm_sect6">

<!--
Once an executable image has been memory mapped into a processes virtual
memory it can start to execute. As only the very start of the image is 
physically pulled into memory it will soon access an area of virtual memory 
that is not yet in physical memory. When a process accesses a virtual address 
that does not have a valid page table entry, the processor will report a page 
fault to Linux. The page fault describes the virtual address where the page 
fault occurred and the type of memory access that caused. 
-->
<p>実行イメージがいったんメモリにマップされてプロセス仮想メモリに入ると、
イメージの実行開始が可能となる。しかし、そのイメージの最初の部分だけしか物理
メモリに入っていないので、すぐに物理メモリ内にない仮想メモリ領域へとアクセス
がある。プロセスが、有効なページテーブルエントリを持たない仮想アドレスに
アクセスしたとき、プロセッサは Linux にページフォルトの発生を報告する。
<newline>[see: handle_mm_fault, in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/memory.c" 
name="mm/memory.c">]<newline>
ページフォルトは、そのページフォルトが発生した仮想アドレスと、発生の原因と
なったメモリアクセスのタイプとの情報を含んでいる。

<!--
Linux must find the vm_area_struct that represents the area of memory that
the page fault occurred in. As searching through the vm_area_struct data
structures is critical to the efficient handling of page faults, these are 
linked together in an AVL (Adelson-Velskii and Landis) tree structure. If 
there is no vm_area_struct data structure for this faulting virtual address, 
this process has accessed an illegal virtual address. Linux will signal the 
process, sending a SIGSEGV signal, and if the process does not have a handler 
for that signal it will be terminated. 
-->
<p>Linux は、ページフォルトが起こったメモリ領域を示している <tt><ref 
id="vm_area_struct" name="vm_area_struct"></tt> 構造体を探す。
<tt>vm_area_struct</tt> データ構造での検索はページフォルト
処理の効率を決定する上で非常に重要なので、それらは、AVL(Adelson-Velskii and 
Landis)木構造にリンクされている。もし、フォルトが起こった仮想アドレスに
関する <tt>vm_area_struct</tt> データ構造体が存在しない場合、このプロセスは、
無効な仮想アドレスにアクセスしたことになる。Linux は、そのプロセスに SIGSEGV 
シグナルを送り、もしそのプロセスが当該シグナルを処理しない場合は、そのプロセス
を終了させる。

<!--
Linux next checks the type of page fault that occurred against the types of
accesses allowed for this area of virtual memory. If the process is accessing 
the memory in an illegal way, say writing to an area that it is only allowed 
to read from, it is also signalled with a memory error. 
-->
<p>次に、Linux は、その仮想メモリ領域のアクセス権限に違反して起こったページ
フォルトのタイプをチェックする。プロセスが、たとえば読み出ししか許されない領域
に書き込みをしようとした場合のように、無効な方法でメモリにアクセスしている
場合、そのプロセスにはメモリエラー(memory error)のシグナルも送られる。

<!--
Now that Linux has determined that the page fault is legal, it must deal with 
it. 
Linux must differentiate between pages that are in the swap file and those that
are part of an executable image on a disk somewhere. It does this by using the
page table entry for this faulting virtual address. 
-->
<p>Linux がページフォルトが正当なものと判断した場合、ページフォルトに対処しな
ければならない。
<newline>[see: do_no_page(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/memory.c" 
name="mm/memory.c">]<newline>
Linux は、スワップファイル内のページとディスクの他の場所にある実行イメージの
一部とを区別しなければならない。それをするためには、フォルトが起こった仮想アド
レスのページテーブルエントリが使用される。

<!--
If the page's page table entry is invalid but not empty, the page fault is for
a page currently being held in the swap file. For Alpha AXP page table entries,
these are entries which do not have their valid bit set but which have a 
non-zero value in their PFN field. In this case the PFN field holds 
information about where in the swap (and which swap file) the page is being 
held. How pages in the swap file are handled is described later in this 
chapter. 
-->
<p>フォルトページのページテーブルエントリが無効だが空でない場合、そのページ
フォルトは、現在スワップファイルに保存されているページのものである。Alpha AXP 
のページテーブルエントリの場合、有効ビットは設定されていないが <ref 
id="chapter_mm_pfn" name="PFN"> フィールドに 0 でない値が設定されている
エントリがある。その場合、PFN フィールドには、
スワップのどこに(そしてどのスワップファイルに)当該ページが保存されているのか
に関する情報が記されている。スワップファイル内のページを操作する方法は、
この章の後の部分で紹介される。

<!--
Not all vm_area_struct data structures have a set of virtual memory
operations and even those that do may not have a nopage operation. This is
because by default Linux will fix up the access by allocating a new physical
page and creating a valid page table entry for it. If there is a nopage 
operation for this area of virtual memory, Linux will use it. 
-->
<p><tt><ref id="vm_area_struct" name="vm_area_struct"></tt> データ構造体のすべ
てが、仮想メモリ操作のセットを持っているわけではなく、nopage 操作すらもっていな
い場合もある。これは、デフォルトでは Linux が、アクセスの問題を解決するために、
新しい物理ページを割り付け、そのための有効なページテーブルエントリを作成するよ
うになっているからである。(<tt>vm_area_struct</tt> に)この仮想メモリ領域に
対する nopage 操作が存在する場合、Linux はそのルーチンを使用する。

<!--
The generic Linux nopage operation is used for memory mapped executable
images and it uses the page cache to bring the required image page into 
physical memory. 
-->
<p>汎用的な Linux の nopege 操作ルーチンは、メモリにマップされた実行イメージに
対して使用されるものなので、その nopage 操作ルーチンは、ページキャッシュを
利用して、必要なイメージページを物理メモリに持ってくる。
<newline>[see: filemap_nopage(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/filemap.c" 
name="mm/filemap.c">]<newline>

<!--
However the required page is brought into physical memory, the processes page
tables are updated. It may be necessary for hardware specific actions to update
those entries, particularly if the processor uses translation look aside 
buffers. Now that the page fault has been handled it can be dismissed and the 
process is restarted at the instruction that made the faulting virtual memory 
access. 
-->
<p>方法はどうあれ、必要なページが物理メモリに置かれた場合は、
プロセスページテーブルはアップデートされる。それらのエントリをアップデート
するためにはハードウェア固有の処理が必要になるかもしれない。特に、プロセッサ
がアドレス操作バッファ(Translation Look-aside Buffer, TLB)を利用している場合は
そうである。これでようやくページフォルトは処理されたので、フォルトは解除さ
れ、プロセスは、仮想メモリアクセスでフォルトを起こした命令の時点から再
スタートされる。

<!--3.7  The Linux Page Cache-->
<sect1>Linux のページキャッシュ<label id="chapter_mm_sect7">
<p>

<label id="figure3-6">
<!--                 Figure 3.6: The Linux Page Cache-->
<#if output="html">
<figure><ph vspace="100"><img src="./The-Linux-Kernel-images/figure3-6.gif">
</figure>
</#if>
<#unless output="html">
<verb>
page_hash_table
+--------------+
|              |         mem_map_t                mem_map_t
|--------------|       +-----------+            +-----------+
|              |------>| inode     |12      +-->| inode     |12
|--------------|       |-----------|        |   |-----------|
|              |       | offset    |0x8000  |   | offset    |0x2000
|--------------|       |-----------|        |   |-----------|
|              |       |           |        |   |           |
|--------------|       |           |        |   |           |
|              |       |           |        |   |           |
|--------------|       |-----------|        |   |-----------|
|              |       | next_hash |--------+   | next_hash |
|              |       |-----------|            |-----------|
|              |       | prev_hash |            | prev_hash |
|              |       |-----------|            |-----------|
|              |       |           |            |           |
|              |       +-----------+            +-----------+
|              |
|--------------|
|              |
|--------------|
|              |
+--------------+
</verb>
</#if>
<p>図表3.6 Linux のページキャッシュ


<!--
The role of the Linux page cache is to speed up access to files on disk. Memory
mapped files are read a page at a time and these pages are stored in the page
cache. Figure  3.6 shows that the page cache consists of the
page_hash_table, a vector of pointers to mem_map_t data structures. 
-->
<p>Linux のページキャッシュの役割は、ディスク上のファイルへのアクセス速度を
上げることである。メモリにマップされたファイルはページ単位で読み出され、それら
のページはページキャッシュに保存される。図表(3.6)では、ページキャッシュが 
<tt><ref id="mem_map_t" name="page_hash_table"></tt> から構成されており、それ
が <tt><ref id="mem_map_t" name="mem_map_t"></tt> データ構造へのポインタの配列
となっていることが示されている。
<newline>[see: <htmlurl 
url="The-Linux-Kernel-images/linux/include/linux/pagemap.h" 
name="include/linux/pagemap.h">]<newline>

<!--
Each file in Linux is identified by a VFS inode data structure (described in
Chapter  filesystem-chapter) and each VFS inode is unique and fully describes
one and only one file. The index into the page table is derived from the 
file's VFS inode and the offset into the file. 
-->
<p>Linux 内のファイルはそれぞれ VFS inode データ構造で識別される(詳細は、
<ref id="chapter_fs" name="「ファイルシステム」">の章で述べる)。VFS inode は
システム上ユニークであり、特定の単一のファイルに関する完全な識別子となる。
ページテーブルへのインデックスは、ファイルの VFS inode とそのファイルへの
オフセットから導き出される。

<!--
Whenever a page is read from a memory mapped file, for example when it needs
to be brought back into memory during demand paging, the page is read through
the page cache. If the page is present in the cache, a pointer to the mem_map_t
data structure representing it is returned to the page fault handling code.
Otherwise the page must be brought into memory from the file system that holds
the image. Linux allocates a physical page and reads the page from the file on
disk. 
-->
<p>メモリにマップされたファイルからページが読み出されるとき、たとえばデマンド
ページングでページがメモリに戻されるときなどには、ページはページキャッシュか
ら読み出される。
ページがキャッシュ内にある場合は、そのキャッシュ内のページを表す <tt><ref 
id="mem_map_t" name="mem_map_t"></tt> データ構造体へのポインタが、ページフォ
ルト処理コードに返される。
そうでない場合は、ページは、そのイメージを保存しているファイルシステムから
メモリ内へと取り出さる必要がある。その場合、Linux は物理ページを割り付けて、
ディスク上のファイルからそのページを読み出す。

<!--
If it is possible, Linux will initiate a read of the next page in the file. 
This single page read ahead means that if the process is accessing the pages 
in the file serially, the next page will be waiting in memory for the process. 
-->
<p>要求がなくても、Linux の側でファイル内の次のページを読み出しておくことも
可能である。この単一ページの先読みは、もしプロセスがファイル内のページに連続
してアクセスしている場合は、そのプロセスのために次のページをメモリ内に待機さ
せることを意味する。

<!--
Over time the page cache grows as images are read and executed. Pages will be
removed from the cache as they are no longer needed, say as an image is no
longer being used by any process. As Linux uses memory it can start to run low
on physical pages. In this case Linux will reduce the size of the page cache. 
-->
<p>イメージが読み出されて実行されていくと、ページキャッシュはだんだんと大きく
なる。必要のなくなったページ、たとえばどのプロセスからもアクセスされなくなった
イメージは、キャッシュから削除される。
メモリの使用量が増えると、物理ページが不足してくることがある。その場合、
Linux はページキャッシュのサイズを小さくする。


<!--3.8  Swapping Out and Discarding Pages-->
<sect1>スワップアウトとページの破棄<label id="chapter_mm_sect8">

<!--
When physical memory becomes scarce the Linux memory management
subsystem must attempt to free physical pages. This task falls to the kernel
swap daemon (kswapd). 
The kernel swap daemon is a special type of process, a kernel thread. Kernel
threads are processes have no virtual memory, instead they run in kernel mode 
in the physical address space. The kernel swap daemon is slightly misnamed in
that it does more than merely swap pages out to the system's swap files. Its
role is make sure that there are enough free pages in the system to keep the
memory management system operating efficiently. 
-->
<p>物理メモリが少なくなると、Linux のメモリ管理サブシステムは、物理ページを
解放するよう努力しなければならない。このタスクは、カーネルスワップデーモン
(kernel swap daemon)(<tt>kswapd</tt>)の仕事である。
カーネルスワップデーモンは、カーネルスレッド(kernel thread)という特別な
プロセスである。
カーネルスレッドは仮想メモリを持たず、そのかわり物理アドレス空間内において
カーネルモードで実行される。このカーネルスワップデーモンは、その役割が
単にページをシステムのスワップファイルに書き出すだけでないことからすると、
やや命名に難があるといえる。その役割は、システム内で充分な空ページを
確保して、メモリ管理システムの操作効率を維持することである。

<!--
The Kernel swap daemon (kswapd) is started by the kernel init process at
startup time and sits waiting for the kernel swap timer to periodically 
expire. 
Every time the timer expires, the swap daemon looks to see if the number of 
free pages in the system is getting too low. It uses two variables, 
free_pages_high and free_pages_low to decide if it should free some pages. So 
long as the number of free pages in the system remains above free_pages_high, 
the kernel swap daemon does nothing; it sleeps again until its timer next 
expires. For the purposes of this check the kernel swap daemon takes into 
account the number of pages currently being written out to the swap file. It 
keeps a count of these in nr_async_pages; this is incremented each time a page
is queued waiting to be written out to the swap file and decremented when the 
write to the swap device has completed. free_pages_low and free_pages_high are
set at system startup time and are related to the number of physical pages in 
the system. If the number of free pages in the system has fallen below 
free_pages_high or worse still free_pages_low, the kernel swap daemon will try
three ways to reduce the number of physical pages being used by the system: 
-->
<p>カーネルスワップデーモン(<tt>kswapd</tt>)は、起動時にカーネル初期化プロセ
スにより起動され、カーネルスワップタイマーが定期的に時間切れになるのを待って
いる。
<newline>[see: kswapd(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/vmscan.c" 
name="mm/vmscan.c">]<newline>
タイマーが時間切れになると、スワップデーモンはシステムの空ページの数が減りす
ぎていないかどうかを確認する。<tt>kswapd</tt>は、<tt>
<ref id="swap_info_struct" name="free_pages_high"></tt> と 
<tt>free_pages_low</tt> のふたつの変数を使ってページを解放するかどうかを判断
する。
システム内の空ページの数が <tt>free_pages_high</tt> よりも多い限り、カーネル
スワップデーモンは何もしない。タイマーが切れるまで再び休憩する。このチェックに
際して、カーネルスワップデーモンは、スワップファイルに現在書き出されている
ページ数を考慮に入れる。カーネルスワップデーモンは、その数を、<tt>
nr_async_pages</tt> に保持している。この数は、スワップファイルに書き出される
ためにページがキューに入れられたときに増加し、スワップデバイスへの書き込みが
完了したときに減少する。<tt>free_pages_high</tt> と <tt>free_page_low</tt> と
は、システム起動時にセットされ、システム内の物理ページの数と関連付けられる。
システム内の空ページの数が <tt>free_page_high</tt> 以下になるか、<tt>
free_pages_low</tt> 以下にまで落ち込んでしまった場合には、カーネルスワップ
デーモンは、3 つの方法を使ってシステムで使用されている物理ページの数を減ら
そうとする。

<!--
      Reducing the size of the buffer and page caches, 
      Swapping out System V shared memory pages, 
      Swapping out and discarding pages. 
-->
<itemize>
<item>バッファとページキャッシュのサイズを減らす。
<item>System V 共有メモリページをスワップアウトさせる。
<item>ページをスワップアウトさせて、破棄する。
</itemize>

<!--
If the number of free pages in the system has fallen below free_pages_low, the
kernel swap daemon will try to free 6 pages before it next runs. Otherwise it 
will try to free 3 pages. Each of the above methods are tried in turn until 
enough pages have been freed. The kernel swap daemon remembers which method it
was using the last time that it attempted to free physical pages. Each time it
runs it will start trying to free pages using this last successful method. 
-->
<p>システムの空ページの数が <tt>free_pages_low</tt> 以下になっている場合、
カーネルスワップデーモンは、次の実行時までに 6 つのページを解放する。でなけれ
ば、3 つのページを解放する。上記の方法は、充分なページが解放されるまで順番に
繰り返される。カーネルスワップデーモンは、物理メモリを解放するとき最後に
使った方法を覚えている。実行の際はいつも、前回の最後に成功した方法を使用して
ページを解放しようとし始める。

<!--
After it has free sufficient pages, the swap daemon sleeps again until its 
timer expires. If the reason that the kernel swap daemon freed pages was that 
the number of free pages in the system had fallen below free_pages_low, it only
sleeps for half its usual time. Once the number of free pages is more than
free_pages_low the kernel swap daemon goes back to sleeping longer between
checks. 
-->
<p>充分な空ページが出来たら、スワップデーモンは、タイマーが切れるまで再び休憩
に入る。カーネルスワップデーモンがページを解放した理由が、システム内の空ページ
の数が <tt>free_pages_low</tt> を下回ったからであった場合は、その休憩時間は、
通常の半分に短縮される。空ページの数が <tt>free_pages_low</tt> の数を超えて
しまえば、カーネルスワップデーモンは通常のタイマー間隔での休憩に戻る。

<!--3.8.1  Reducing the Size of the Page and Buffer Caches-->
<sect2>ページキャッシュとバッファキャッシュのサイズの縮小<label 
id="chapter_mm_sect8-1">

<!--
The pages held in the page and buffer caches are good candidates for being 
freed into the free_area vector. The Page Cache, which contains pages of memory
mapped files, may contain unneccessary pages that are filling up the system's
memory. Likewise the Buffer Cache, which contains buffers read from or being
written to physical devices, may also contain unneeded buffers. When the
physical pages in the system start to run out, discarding pages from these
caches is relatively easy as it requires no writing to physical devices (unlike
swapping pages out of memory). Discarding these pages does not have too
many harmful side effects other than making access to physical devices and
memory mapped files slower. However, if the discarding of pages from these
caches is done fairly, all processes will suffer equally. 
-->
<p>ページキャッシュとバッファキャッシュに保存されているページは、解放して <tt>
<ref id="free_area" name="free_area"></tt> 配列に入れるべき有力な候補者である。
ページキャッシュには、メモリにマップされたファイルのページが含まれているので、
メモリを満杯にしている不要なページが含まれている場合がある。同様に、バッファ
キャッシュには、物理デバイスに対する読み書きの結果としてのバッファが含まれてい
るので、ここにも必要のないバッファが含まれている場合がある。
システム内の物理ページが不足し始めると、これらのキャッシュからページを削除する
ことは相対的に容易になる。ページをメモリからスワップアウトさせる場合と異なり、
それらは、物理デバイスへの書き込みを必要としないからである。キャッシュから不要
なページをいくつか破棄したとしても、物理デバイスやメモリにマップされたファイル
へのアクセスが遅くなる以外には、目立った有害な副作用はない。しかし、もしそれら
のキャッシュからページをすべて破棄したとしたら、全プロセスが等しく悪影響を受
ける。

<!--
Every time the Kernel swap daemon tries to shrink these caches 
it examines a block of pages in the mem_map page vector to see if any can be
discarded from physical memory. The size of the block of pages examined is
higher if the kernel swap daemon is intensively swapping; that is if the 
number of free pages in the system has fallen dangerously low. The blocks of 
pages are examined in a cyclical manner; a different block of pages is 
examined each time an attempt is made to shrink the memory map. This is known 
as the clock algorithm as, rather like the minute hand of a clock, the whole 
mem_map page vector is examined a few pages at a time. 
-->
<p>カーネルスワップデーモンは、これらのキャッシュを縮小しようとするたびに、
<tt>page</tt> の配列 <tt><ref id="mem_map_t" name="mem_map"></tt> 内のページ
ブロックを調べて、物理メモリから削除できるものがないかどうかを確認する。
<newline>[see: shrink_mmap(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/filemap.c" 
name="mm/filemap.c">]<newline>
カーネルスワップデーモンが熱心にスワップ処理をしている場合、すなわちシステム
の空ページの数が危険なほど低下している場合には、より大きなサイズのページ
ブロックが調査される。ページブロックの調査は循環的な方法でなされる。すなわち、
メモリマップを縮小しようとするたびごとに違うサイズのページブロックが調査され
る。この方法は、時計の分針に似ていることからクロックアルゴリズム
(clock algorithm)と呼ばれ、<tt>page</tt> の配列 <tt><ref id="mem_map_t" 
name="mem_map"></tt> 全体が、一度に数ページ単位で調査される。

<!--
Each page being examined is checked to see if it is cached in either the page
cache or the buffer cache. You should note that shared pages are not considered
for discarding at this time and that a page cannot be in both caches at the 
same time. If the page is not in either cache then the next page in the 
mem_map page vector is examined. 
-->
<p>個々のページを調査する際は、そのページがページキャッシュかバッファキャッシュ
にキャッシュされているかどうか確認される。
注意すべきなのは、この時点では共有ページは破棄されないこと、および同時に両方の
キャッシュに入っているページは存在しないことである。
当該ページがどちらのキャッシュにも入っていない場合、<tt>page</tt> の配列 <tt>
mem_map</tt> の次のページが調査される。

<!--
Pages are cached in the buffer cache (or rather the buffers within the pages 
are cached) to make buffer allocation and deallocation more efficient. The 
memory map shrinking code tries to free the buffers that are contained within 
the page being examined. 
If all the buffers are freed, then the pages that contain them are also be 
freed. If the examined page is in the Linux page cache, it is removed from the
page cache and freed. 
-->
<p>ページがバッファキャッシュにキャッシュされるのは(あるいは、バッファがページ
キャッシュにキャッシュされるのは)、バッファの割り付けと解放とをより効率的に
行うためである。メモリ縮小コードは調査が終わったページのバッファから、解放しよ
うとする。
<newline>[see: try_to_free_buffer, in <htmlurl 
url="./The-Linux-Kernel-images/linux/fs/buffer.c" 
name="fs/buffer.c">]
それらすべてのバッファが解放されると、それらを含むページも解放される。調査
されたページが Linux のページキャッシュに入っている場合、それはページ
キャッシュから削除され解放される。

<!--
When enough pages have been freed on this attempt then the kernel swap
daemon will wait until the next time it is periodically woken. As none of the 
freed pages were part of any process's virtual memory (they were cached pages),
then no page tables need updating. If there were not enough cached pages
discarded then the swap daemon will try to swap out some shared pages. 
-->
<p>この作業によって充分なページが解放されたら、カーネルスワップデーモンは、
次の定期的呼び出しまで休憩する。解放されたページはどのプロセスの仮想メモリ
の一部にもなっていなかったので(それらはキャッシュされたページであったので)、
どのページテーブルもアップデートされる必要がない。キャッシュされたページが
充分に解放されない場合、スワップデーモンは共有ページのいくつかをスワップアウト
しようとする。

<!--3.8.2  Swapping Out System V Shared Memory Pages-->
<sect2>System V 共有メモリページのスワップアウト<label id="chapter_mm_sect8-2">

<!--
System V shared memory is an inter-process communication mechanism which
allows two or more processes to share virtual memory in order to pass
information amongst themselves. How processes share memory in this way is
described in more detail in Chapter  IPC-chapter. For now it is enough to say
that each area of System V shared memory is described by a shmid_ds data
structure. This contains a pointer to a list of vm_area_struct data structures,
one for each process sharing this area of virtual memory. The
vm_area_struct data structures describe where in each processes virtual
memory this area of System V shared memory goes. Each vm_area_struct
data structure for this System V shared memory is linked together using the
vm_next_shared and vm_prev_shared pointers. Each shmid_ds data
structure also contains a list of page table entries each of which describes 
the physical page that a shared virtual page maps to. 
-->
<p>System V 共有メモリとは、プロセス間通信のメカニズムであり、ふたつ以上の
プロセスがお互いに情報を交換するために仮想メモリを共有することを許す仕組み
である。この方法でどのようにプロセスがメモリを共有するかについては、
<ref id="chapter_ipc_sect3-4" name="「プロセス間通信の仕組み」">の章で詳細に
解説する。今のところ、System V 共有メモリのそれぞれのエリアは、<tt><ref 
id="shmid_ds" name="shmid_ds"></tt> データ構造体により記述されているとだけ
述べておく。
これには、<tt><ref id="vm_area_struct" name="vm_area_struct"></tt> データ構造体
のリストへのポインタが含まれている。その個々の <tt>vm_area_struct</tt> データ
構造体は、仮想メモリの当該領域を共有するプロセスのものであり、それぞれのプロセ
スの仮想メモリのどこに System V 共有メモリの領域があるのかを記述するものであ
る。System V 共有メモリのための <tt>vm_area_struct</tt> データ構造体はそれぞ
れ、<tt><ref id="vm_area_struct" name="vm_next_shared"></tt> と <tt>
vm_prev_shared</tt> ポインタを使ってお互いにリンクされている。
個々の <tt>shmid_ds</tt> データ構造体には、ページテーブルエントリのリストが含ま
れていて、それぞれ共有仮想ページがマップされている物理ページを記述している。

<!--
The kernel swap daemon also uses a clock algorithm when swapping out System
V shared memory pages. . Each time it runs it remembers which page of which 
shared virtual memory area it last swapped out. It does this by keeping two 
indices, the first is an index into the set of shmid_ds data structures, the 
second into the list of page table entries for this area of System V shared 
memory. This makes sure that it fairly victimizes the areas of System V 
shared memory. 
-->
<p>カーネルスワップデーモンは、System V 共有メモリページをスワップアウトする
時にもクロックアルゴリズムを使用する。それが実行される際はいつも、どの共有仮想
メモリエリアのどのページを最後にスワップアウトしたか、カーネルスワップデーモン
は覚えている。それを実現するために、スワップデーモンはふたつのインデックスを
使用する。ひとつは、<tt><ref id="shmid_ds" name="shmid_ds"></tt> データ構造体
のセットへのインデックスであり、もうひとつは、System V 共有メモリの該当エリア
に関するページテーブルエントリのリストへのインデックスである。それによって、
System V 共有メモリに対して公正な負担が課されるようになっている。

<!--
As the physical page frame number for a given virtual page of System V shared
memory is contained in the page tables of all of the processes sharing this 
area of virtual memory, the kernel swap daemon must modify all of these page 
tables to show that the page is no longer in memory but is now held in the 
swap file. For each shared page it is swapping out, the kernel swap daemon 
finds the page table entry in each of the sharing processes page tables (by 
following a pointer from each vm_area_struct data structure). If this 
processes page table entry for this page of System V shared memory is valid, 
it converts it into an invalid but swapped out page table entry and reduces 
this (shared) page's count of users by one. The format of a swapped out System
V shared page table entry contains an index into the set of shmid_ds data 
structures and an index into the page table entries for this area of System V 
shared memory. 
-->
<p>System V共有メモリの仮想ページに対する物理ページフレーム番号は、該当する仮想
メモリエリアを共有するすべてのプロセスのページテーブル内に含まれているので、
カーネルスワップデーモンはこれらすべてのページテーブルを書き換えて、該当ページ
はもはやメモリ内にはなく、スワップファイルに保存されているということを示さな
ければならない。共有ページはひとつずつスワップアウトされるので、カーネル
スワップデーモンは、個々の共有プロセスのページテーブル内のページテーブル
エントリを探す。(これは、個々の <tt><ref id="vm_area_struct" 
name="vm_area_struct"></tt> データ構造体のポインタを追跡することにより実行され
る。)
もし、その System V 共有メモリエリアに対するプロセスのページエントリーテーブル
が有効ならば、スワップデーモンは、それを無効だがスワップアウトされたページ
テーブルエントリである旨に書き換えて、その(共有)ページのユーザ数カウントを
ひとつ減少させる。スワップアウトされた System V 共有ページのテーブルエントリの
フォーマットには、<tt><ref id="shmid_ds" name="shmid_ds"></tt> データ構造体の
セットへのインデックスと その System V 共有メモリエリアに対するページテーブル
エントリへのインデックスとが含まれる。

<!--
If the page's count is zero after the page tables of the sharing processes have
all been modified, the shared page can be written out to the swap file. The 
page table entry in the list pointed at by the shmid_ds data structure for 
this area of System V shared memory is replaced by a swapped out page table 
entry. A swapped out page table entry is invalid but contains an index into 
the set of open swap files and the offset in that file where the swapped out 
page can be found. This information will be used when the page has to be 
brought back into physical memory. 
-->
<p>共有プロセスのページテーブルが完全に書き換えられてページカウントがゼロに
なると、共有ページをスワップファイルに書き出すことが可能になる。その System 
V 共有メモリエリアに対するページテーブルエントリのなかで、<tt>shmid_ds</tt> 
データ構造体によって指示されたリスト内に存在するものは、スワップアウトされた
ページテーブルのエントリ(swapped out page table entry)によって置き換えられ
る。スワップアウトされたページテーブルのエントリは無効だが、スワップファイルを
オープンするためのセットへのインデックスと、そのファイル内でスワップ
アウトされたページを探すためのオフセットとが含まれている。この情報が使用され
るのは、そのページが物理メモリ内に再度戻されるときである。

<!--3.8.3  Swapping Out and Discarding Pages-->
<sect2>スワップアウトされたか破棄されたページ<label id="chapter_mm_sect8-3">

<!--
The swap daemon looks at each process in the system in turn to see if it is a
good candidate for swapping. Good candidates are processes that can be swapped
(some cannot) and that have one or more pages which can be swapped or 
discarded from memory. Pages are swapped out of physical memory into the 
system's swap files only if the data in them cannot be retrieved another way. 
-->
<p>スワップデーモンはシステム内のプロセスを順番に調べて、スワップすべき有力
候補がいないかどうかを探す。
<newline>[see: swap_out(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/vmscan.c" 
name="mm/vmscan.c">]<newline>
候補者とは、スワップ可能で(不可能なプロセスもあ
る)、メモリ内からスワップか破棄することが可能なひとつ以上のページを持っている
プロセスである。ページが物理メモリからスワップアウトされてシステムのスワップ
ファイルに入れられるのは、ページ内のデータがスワップ以外の方法では元に戻せな
い場合だけである。

<!--
A lot of the contents of an executable image come from the image's file and can
easily be re-read from that file. For example, the executable instructions of 
an image will never be modified by the image and so will never be written to 
the swap file. These pages can simply be discarded; when they are again 
referenced by the process, they will be brought back into memory from the 
executable image. 
-->
<p>実行イメージの内容の多くはそのイメージのファイルからメモリ内に置かれている
ので、その内容の再読み出しは簡単に実行できる。たとえば、あるイメージの実行命令
は、そのイメージによって修正されることはないので、それがスワップファイルに書き
込まれることは決してない。それらのページは単に破棄されるだけである。プロセス
から再度参照される時は、実行イメージからメモリ内に戻せばいいからである。

<!--
Once the process to swap has been located, the swap daemon looks through all
of its virtual memory regions looking for areas which are not shared or 
locked. Linux does not swap out all of the swappable pages of the process 
that it has selected; instead it removes only a small number of pages. 
Pages cannot be swapped or discarded if they are locked in memory. 
-->
<p><label id="chapter_mm_lock">
スワップすべきプロセスが見つかったら、スワップデーモンはそのプロセスの仮想
メモリ領域を走査して共有されたりロック(lock)されたりしていないエリアを探す。
Linux 
は、選択したプロセスのスワップ可能なすべてのページをスワップするわけではない。
むしろ、ごく少数のページだけを削除する。メモリ内でロックされている場合、ページ
はスワップも破棄もできない。<newline>
(原注: この操作は、当該プロセスの <tt><ref id="mm_struct" name="mm_struct">
</tt> 上でキューイングされた <tt>vm_area_struct</tt> 構造体のリストにある 
<tt>mv_next</tt> ポインタを順に検査することで実行される。)

<!--
The Linux swap algorithm uses page aging. Each page has a counter (held in the
mem_map_t data structure) that gives the Kernel swap daemon some idea
whether or not a page is worth swapping. Pages age when they are unused and
rejuvinate on access; the swap daemon only swaps out old pages. The default
action when a page is first allocated, is to give it an initial age of 3. 
Each time it is touched, it's age is increased by 3 to a maximum of 20. Every 
time the Kernel swap daemon runs it ages pages, decrementing their age by 1. 
These default actions can be changed and for this reason they (and other swap 
related information) are stored in the swap_control data structure. 
-->
<p>Linux のスワップアルゴリズムは、ページエイジング(page aging)を使っている。
<newline>[see: swap_out_vma(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/vmscan.c" 
name="mm/vmscan.c">]<newline>
ページはそれぞれ(<tt><ref id="mem_map_t" name="mem_map_t"></tt> 構造体の中に)
カウンタを持っていて、それによってカーネルスワップデーモンにページがスワップ
されるべきかどうかを伝えている。
ページが使用されなかったりアクセスによって若返らない場合に、ページは歳を取る。
スワップデーモンは高齢のページだけをスワップアウトさせる。ページを最初に
割り付けるときのデフォルトの操作では、最初に 3 の寿命を与える。
アクセスがあるたびに、年齢は 3 から最大 20 まで上がる。カーネルスワップ
デーモンが実行されると、そのたびにページを加齢し、その年限をひとつずつ引いて
いく。こうしたデフォルトの操作は変更可能であり、それゆえ、設定値(と、その他の
スワップに関係した情報)は、<tt><ref id="swap_control" name="swap_control">
</tt> データ構造体に保存されている。

<!--
If the page is old (age = 0), the swap daemon will process it further. Dirty 
pages are pages which can be swapped out. Linux uses an architecture specific 
bit in the PTE to describe pages this way (see Figure  3.2). However, not all 
dirty pages are necessarily written to the swap file. Every virtual memory 
region of a process may have its own swap operation (pointed at by the vm_ops 
pointer in the vm_area_struct) and that method is used. Otherwise, the swap 
daemon will allocate a page in the swap file and write the page out to that 
device. 
-->
<p>ページの寿命が尽きたら(age=0)、スワップデーモンはさらにその処理を進める。
修正されているページ(dirty page)は、スワップアウトすることができる。Linux は、
PTE 内のアーキテクチャに固有のビットを使ってそれを区別する。
(<ref id="figure3-2" name="図表(3.2)"> 参照)
しかし、dirty page がすべてスワップファイルに書き出される必要はない。
あらゆるプロセスの仮想メモリ領域は、それ自身に必要なスワップ操作が指定されて
いるかもしれず(それは、<tt><ref id="vm_area_struct" name="vm_area_struct">
</tt> 内の <tt>vm_ops</tt> ポインタ
で示される)、そこでの方法が利用されるからである。そうでない場合、スワップ
デーモンは、ページをスワップファイルに割り付け、スワップデバイスに書き出す。

<!--
The page's page table entry is replaced by one which is marked as invalid but
which contains information about where the page is in the swap file. This is an
offset into the swap file where the page is held and an indication of which 
swap file is being used. Whatever the swap method used, the original physical 
page is made free by putting it back into the free_area. Clean (or rather not 
dirty) pages can be discarded and put back into the free_area for re-use. 
-->
<p>スワップアウトされたページのページテーブルエントリは、無効とマークされた
エントリによって置き換えられるが、そのエントリには、ページのスワップファイル
内の位置に関する情報が含まれている。その情報は、スワップファイル内のどこに
ページが保存されているかを表すオフセット値と、どのスワップファイルが使用され
たかを示す指示子から成る。
どのようなスワップメソッドが使用された場合でも、もとの物理ページは解放され、
<tt><ref id="free_area" name="free_area"></tt> の中に入れられる。内容の変更
されていない(あるいは、修正されていない(not dirty))ページは、破棄されて、
再利用のために <tt>free_area</tt> に入れられる。

<!--
If enough of the swappable processes pages have been swapped out or
discarded, the swap daemon will again sleep. The next time it wakes it will
consider the next process in the system. In this way, the swap daemon nibbles
away at each processes physical pages until the system is again in balance.
This is much fairer than swapping out whole processes. 
-->
<p>スワップ可能なプロセスのページが、充分な数だけスワップアウトされるか
破棄された場合、スワップデーモンは再度スリープする。次に起きるときは、システ
ム内の次のプロセスを対象として考慮する。この方法によって、スワップデーモンは
システムがバランスを取り戻すまで、プロセスの物理ページを少しずつ解放してい
く。この方法は、プロセス全体をスワップアウトするよりもずっと公平である。


<!--3.9  The Swap Cache-->
<sect1>スワップキャッシュ<label id="chapter_mm_sect9">

<!--
When swapping pages out to the swap files, Linux avoids writing pages if it
does not have to. There are times when a page is both in a swap file and in
physical memory. This happens when a page that was swapped out of memory
was then brought back into memory when it was again accessed by a process.
So long as the page in memory is not written to, the copy in the swap file
remains valid. 
-->
<p>ページをスワップファイルに移す際、Linux は必要がなければページを書き
込まない。あるページがスワップファイルと物理メモリの両方に存在するときがある。
そのようなことが起こるのは、スワップされてメモリから削除されていたページが
プロセスに再度アクセスされたことでメモリに戻った場合である。メモリにある
ページが書き込みを受けていない限り、スワップファイルにあるページのコピーは
有効なままである。

<!--
Linux uses the swap cache to track these pages. The swap cache is a list of
page table entries, one per physical page in the system. This is a page table
entry for a swapped out page and describes which swap file the page is being
held in together with its location in the swap file. If a swap cache entry is
non-zero, it represents a page which is being held in a swap file that has not
been modified. If the page is subsequently modified (by being written to), its
entry is removed from the swap cache. 
-->
<p>Linux はそのようなページを監視するためにスワップキャッシュを使う。スワップ
キャッシュはページテーブルエントリのリストであり、エントリはシステム上の物理
ページごとに存在する。これは、スワップアウトしたページのページテーブル
エントリであり、そのページがどのスワップファイルに保存されているかということ
と、そのスワップファイル内での位置とが記されているものである。スワップキャッ
シュエントリがゼロでない場合、それは、そのページがスワップファイル内にあり、
しかもそれが変更されていないということを表している。ページの中味がその後で
(書き込みをされて)変更された場合、そのエントリはスワップキャッシュから削除
される。

<!--
When Linux needs to swap a physical page out to a swap file it consults the
swap cache and, if there is a valid entry for this page, it does not need to 
write the page out to the swap file. This is because the page in memory has 
not been modified since it was last read from the swap file. 
-->
<p>Linux が物理ページをスワップファイルにスワップアウトする必要がある場合、
スワップキャッシュをまず調べる。スワップキャッシュにそのページ用の有効な
エントリがあるなら、そのページをスワップファイルに書き出す必要はない。
なぜなら、メモリ内のそのページは、スワップファイルから最後に読み出されて以来
変更されていないからである。

<!--
The entries in the swap cache are page table entries for swapped out pages.
They are marked as invalid but contain information which allow Linux to find 
the right swap file and the right page within that swap file. 
-->
<p>スワップキャッシュのエントリはスワップアウトされたページに関するページテー
ブルのエントリである。それらは無効とマークされているが、どのスワップファイル
のどこでそのページが見つかるかを Linux に知らせる情報を含んでいる。

<!--3.10  Swapping Pages In-->
<sect1>スワップのページイン<label id="chapter_mm_sect10">

<!--
The dirty pages saved in the swap files may be needed again, for example when
an application writes to an area of virtual memory whose contents are held in a
swapped out physical page. Accessing a page of virtual memory that is not held
in physical memory causes a page fault to occur. The page fault is the 
processor signalling the operating system that it cannot translate a virtual 
address into a physical one. In this case this is because the page table entry
describing this page of virtual memory was marked as invalid when the page was
swapped out. The processor cannot handle the virtual to physical address 
translation and so hands control back to the operating system describing as it
does so the virtual address that faulted and the reason for the fault. The 
format of this information and how the processor passes control to the 
operating system is processor specific. 
-->
<p>書き込みをされてスワップファイルに保存されたページが再度必要となることが
ある。たとえば、アプリケーションが仮想メモリのある領域に書き込みをしたいのだ
が、その内容が物理ページからスワップアウトされていた場合などである。物理メモリ
上にない仮想メモリのページにアクセスがあった場合、ページフォルトが起こる。
ページフォルトとは、プロセッサがオペレーティングシステムにシグナルを送って、
仮想アドレスを物理アドレスに変換できないことを伝えることである。この場合、
原因は、仮想メモリの該当ページの情報を記しているページテーブルのエントリが、
ページがスワップアウトされる際に無効とマークされるからである。プロセッサは
その仮想アドレスを物理アドレスに変換できないので、制御をオペレーティングシス
テムに手渡して、仮想アドレスがフォルトを起こしたこととそのフォルトの理由とを
伝える。この情報のフォーマットとプロセッサがオペレーティングシステムに制御を
渡す方法とは、プロセッサ固有のものである。
<newline>[see: do_page_fault(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/arch/i386/mm/fault.c" 
name="arch/i386/mm/fault.c">]<newline>

<!--
The processor specific page fault handling code must locate the
vm_area_struct data structure that describes the area of virtual memory that
contains the faulting virtual address. It does this by searching the
vm_area_struct data structures for this process until it finds the one
containing the faulting virtual address. This is very time critical code and a
processes vm_area_struct data structures are so arranged as to make this
search take as little time as possible. 
-->
<p>プロセッサ固有のページフォルト処理コードは、まず必要な <tt><ref 
id="vm_area_struct" name="vm_struct"></tt> データ構造を探さなければならない。
<tt>vm_area_struct</tt>は、仮想メモリのエリアを記述したものであり、そのフォルト
が起きた仮想メモリアドレスを含んでいるからである。
フォルト処理コードは、それらの構造体を検索し、フォルトを起こした仮想アドレスを
含むものを見つけだす。これらは、決して長時間掛かってはいけない(time critical)
コードや処理であるので、<tt>vm_area_struct</tt> 構造体は、検索時間が最短になる
ように並べられている。


<!--
Having carried out the appropriate processor specific actions and found that 
the faulting virtual address is for a valid area of virtual memory, the page 
fault processing becomes generic and applicable to all processors that Linux 
runs on. 
The generic page fault handling code looks for the page table entry for the
faulting virtual address. If the page table entry it finds is for a swapped 
out page, Linux must swap the page back into physical memory. The format of 
the page table entry for a swapped out page is processor specific but all 
processors mark these pages as invalid and put the information neccessary to 
locate the page within the swap file into the page table entry. Linux needs 
this information in order to bring the page back into physical memory. 

-->
<p>プロセッサ固有の動作を適切に処理し、フォルトが起きた仮想アドレスが有効な
仮想メモリ領域にあることが分かった場合、その後のページフォルト処理は、Linux 
が稼働するどのプロセッサにも汎用的で適用可能なものとなる。
<newline>[see: do_no_page(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/memory.c" 
name="mm/memory.c">]<newline>
汎用のページフォルト処理コードは、フォルトを起こした仮想アドレスのページ
テーブルエントリを探す。探し出したページテーブルエントリがスワップアウトされた
ページのものであった場合、Linux はページを物理メモリに戻さなければならない。
スワップアウトされたページに対するページテーブルのエントリはプロセッサ固有の
ものだが、すべてのプロセッサはそれらのページを無効とマークしてあり、そのページ
テーブルエントリにはスワップファイル内で該当ページを見つける際に必要な情報が
書き込まれている。Linux はこの情報を使って、そのページを物理メモリに呼び戻す。
<newline>[see: do_swap_page(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/mm/memory.c"
name="mm/memory.c">]

<!--
At this point, Linux knows the faulting virtual address and has a page table 
entry containing information about where this page has been swapped to. The
vm_area_struct data structure may contain a pointer to a routine which will
swap any page of the area of virtual memory that it describes back into 
physical memory. This is its swapin operation. If there is a swapin operation 
for this area of virtual memory then Linux will use it. This is, in fact, how 
swapped out System V shared memory pages are handled as it requires special 
handling because the format of a swapped out System V shared page is a little 
different from that of an ordinairy swapped out page. There may not be a swapin
operation, in which case Linux will assume that this is an ordinairy page that
does not need to be specially handled. 
It allocates a free physical page and reads the swapped out page back from the
swap file. Information telling it where in the swap file (and which swap file)
is taken from the the invalid page table entry. 
-->
<p>この時点で、Linux は、フォルトが起こった仮想アドレスを知っており、該当
ページがどこにスワップアウトされているかに関する情報を含むページテーブル
エントリを持っている。<tt><ref id="vm_area_struct" name="vm_area_struct"></tt> 
構造体にはある<ref id="vm_operations_struct" name="ルーチン">へのポインタが含ま
れている場合があり、そのルーチンは、その <tt>vm_area_struct</tt> 構造体
で記述している仮想メモリ領域の任意のページを物理メモリへと戻す処理をする。
これは、スワップイン(swapin)操作と呼ばれる。
<newline>[see: shm_swap_in(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/ipc/shm.c" 
name="ipc/shm.c">]<newline>
その仮想メモリエリアにスワップイン処理ルーチンが存在する場合、Linux はその
ルーチンを使用する。これは実際、スワップアウトされた System V 共有メモリ
ページが処理される方法でもある。スワップアウトされた System V 共有ページの
フォーマットは通常のスワップアウトされたページのフォーマットとは少し異なるの
で、それには特別な処理方法が必要とされるからである。しかし、そうした
スワップイン処理ルーチンが存在しない場合もあるので、その際には、Linux は、
そのページが特別な処理を必要としない通常のページであると推定する。
<newline>[see: swap_in(), in <htmlurl 
url="The-Linux-Kernel-images/linux/mm/page_alloc.c" 
name="mm/page_alloc.c">]<newline>
そして、空の物理ページを割り当て、スワップファイルからスワップアウトされた
ページを読み出す。ページがスワップファイルのどこに(およびどのスワップファイル
に)あるかを示す情報は、無効とマークされたそのページテーブルエントリから取得
される。

<!--
If the access that caused the page fault was not a write access then the page 
is left in the swap cache and its page table entry is not marked as writable. 
If the page is subsequently written to, another page fault will occur and, at 
that point, the page is marked as dirty and its entry is removed from the swap
cache. If the page is not written to and it needs to be swapped out again, 
Linux can avoid the write of the page to its swap file because the page is 
already in the swap file. 
-->
<p>ページフォルトを発生させたアクセスが書き込みアクセスでない場合、ページは
スワップキャッシュにそのまま残され、そのページテーブルエントリも書き込み可能
とはマークされない。その後、そのページへの書き込みアクセスが発生すると、その
時点で別なページフォルトが生じ、該当するページ dirty とマークされ、そのエント
リはスワップキャッシュから削除される。
そのページが書き込みされずに、再度スワップアウトされ
る必要が生じた場合、そのページは既にスワップファイルに存在するので、Linux は
ページをあらためてスワップファイルに書き込みせずに済ませることができる。

<!--
If the access that caused the page to be brought in from the swap file was a
write operation, this page is removed from the swap cache and its page table
entry is marked as both dirty and writable. 
-->
<p>ページがスワップファイルから取ってこられるきっかけを作ったアクセスが書き込み
操作であった場合、そのページはスワップキャッシュから削除され、そのページテー
ブルエントリは、dirty かつ書き込み可能であるとマークされる。

<!--
Footnotes:

1 Confusingly the structure is also known as the page structure. 
2 Bibliography reference here 
-->
<footnote>
<label id="chapter_mm_fn1">
(脚注1)紛らわしいことに、この構造体は、ページ構造体とも呼ばれている。<newline>
(脚注2)ここに参考文献を置くこと。
</footnote>