ページフォールト

**ページフォールト** (**page fault**) とは、プログラムが物理メモリがマップされていない仮想アドレス空間上のページにアクセスしたときにハードウェアが発生する割り込み（または例外）である。ページフォールトを処理するソフトウェアは一般にオペレーティングシステム (OS) の一部であり、ページフォールトを発生させるハードウェアを一般にメモリ管理ユニットと呼ぶ。OSのメモリ管理がページフォールトを処理し、その仮想アドレスにアクセスできるようにするか、無効なアクセスであるとしてページフォールトを発生させたプログラムを強制終了させることができる。

名前にフォールト（障害）とあるものの、ページフォールトは必ずしも致命的なエラーではない。Windows、UNIX/Unix系OS（macOS、Linux、*BSD、Solaris、AIX、HP-UXなど）、z/OSといった仮想記憶方式を採用するOSでは、ページフォールトは普通に発生するし、必須な機能でもある。マイクロソフトは（Windows Vistaなどの）リソースモニタの最近のバージョンで、ページフォールトの意味で「ハードフォールト」(hard fault) という呼称を使っている。

## 種類
ページフォールトは、以下のように分類される。
### マイナー
ページフォールト発生時、問題の物理ページがメモリ上にあるが、メモリ管理ユニットがそれをあるものとして扱っていない場合、そのページフォールトはマイナーあるいはソフトなページフォールトである。つまり必要な内容（特定ファイルの特定オフセットの内容）を持つ物理ページは存在するが、（動作中プロセスの）ページテーブルのページフォールトを発生させた仮想アドレスに対応するエントリに登録されていない状態である。OSのページフォールト・ハンドラは単にその物理ページを問題のページテーブルエントリに登録すればよく、二次記憶装置から物理メモリに内容を読み込む必要はない。このような状況は例えば共有メモリを使っていて、共有する相手側プログラムが先に共有メモリにアクセスし、物理メモリ上に内容が存在している場合に起きる。プロセスのワーキングセットからページを削除した場合も、ディスクに書き戻して消去するまでそのページはキャッシュとして保持され、同様の状況になりうる。例えばOpenVMSはワーキングセットが大きすぎると判断すると、ディスクに書き戻す必要のないページ（ディスクから読み込んだ後、一度も内容を変更されていないページなど）を除去し、フリーなページのリストにつなぐ。しかし、そのページを別の用途に再利用するまで内容はそのまま保持されるので、もともとそのページを使用していたプロセスがそのページの対応していた仮想アドレスを参照すると、マッピングを元に戻すことが可能である。マイナーなページフォールトではディスクアクセスが発生しないので、高速に処理できる。

### メジャー
ページフォールト発生時、問題のページがメモリ上にロードされていない場合、そのページフォールトはメジャーあるいはハードなページフォールトである。OSのページフォールト・ハンドラはフリーな物理ページを探し、なければ現に使われているページから再利用する物理ページを選ぶ（ページ置換アルゴリズム）。選択した物理ページの現在の内容が二次記憶装置に書き戻されていない場合、書き戻して完了を待つ必要がある。そして、必要なページ内容を二次記憶装置からその物理ページに読み込む。ここまで処理すると、やっとマイナーなページフォールトと同じ状況になり、後の処理は同じである。二次記憶装置の入出力を待ち合わせる必要があるため、メジャーなページフォールトを起こしたプログラム（プロセス）は即座に処理を再開することはできない。仮想記憶で物理メモリ容量以上のメモリ要求に対応できるのは、この機構のおかげである。

### 無効
ページフォールトの発生した仮想アドレスがそのときの仮想アドレス空間で定義されていないアドレスだった場合、物理ページを問題の仮想アドレスにマッピングすることはできない。このようなページフォールトは無効 (invalid) と呼ばれる。OSのページフォールト・ハンドラは、その参照を行ったコードを終了させるか、無効な参照を行ったことをそのコードに通知する必要がある。ヌルポインタは一般にアドレス0へのポインタとして表されるが、多くのOSは0番地を含む仮想ページは決してマッピングされないようにしている。そのためヌルポインタを使った参照は無効なページフォールトとなる。

## 不正アクセスの扱いと無効ページフォールト
不正アクセスと無効ページフォールトはセグメンテーション違反やバスエラーを起こし、OSの環境によってはプログラムをクラッシュさせたり、コアダンプを生じさせたりする。その多くはソフトウェアのバグだが、オーバークロックなどが原因でハードウェアが誤動作し、ポインタの中身が壊れて発生することもある。

WindowsやUnix系のOSはそれぞれ、ページフォールトに起因するエラーを報告する独自の機構を備えている。Windowsは構造化例外ハンドリングを使ってページフォールトに起因する無効アクセスをセグメンテーション違反として通知する。Unix系では一般にシグナル機構を使い（SIGSEGVなど）、プログラムにエラー状態を通知する。

プログラムがエラー通知を受け取らない場合、OSはデフォルトの動作を行う。一般的には問題を起こした動作中プロセスを終了させ、ユーザーに対してそのプログラムが誤動作したことを通知する。最近のWindowsでは単に "this program must close" のようなメッセージだけを示す（熟練したユーザーやプログラマはデバッガを使って詳細情報を集めることもできる）。最近のWindowsはまた、ミニダンプ（原理的にはコアダンプと同じ）を書き出すことができ、クラッシュしたプロセスの状態を残すことができる。Unix系OSではユーザーに対しては "segmentation violation" や "bus error" といったエラーメッセージを示し、同時にコアダンプを残すこともある。

## 性能
ページフォールトは、プログラムまたはOSの性能を低下させる性質があり、最悪の場合スラッシングが発生する。プログラムやオペレーティングシステムの最適化によってページフォールト回数を減らして性能向上を図ることもある。このときの最適化の観点は、メモリ使用量を減らすこととメモリアクセスの局所性を改善することである。もちろん、物理メモリ量を増やすことでも性能は改善する。ページフォールトに対処するページ置換アルゴリズムは様々存在し、ヒューリスティック的アルゴリズムを使ってページフォールトの回数を減らそうとしている。

典型的なハードディスクの回転レイテンシは3ミリ秒、シーク時間は5ミリ秒、転送時間はページ当たり0.05ミリ秒とする（:en:Disk-drive performance characteristics）。するとページングにかかる総時間は8ミリ秒ほどになる。メモリアクセス時間が200ナノ秒だとすれば、ページフォールトは4万倍も遅いということになる。そのため性能低下が致命的なシステムではページフォールトをなるべく減らすのが重要であり、適切なページ置換アルゴリズムを使ってページヒット率を向上させる必要がある。

## 脚注

## 参考文献

* John L. Hennessy, David A. Patterson, *Computer Architecture, A Quantitative Approach* (ISBN 1-55860-724-2)
* Tanenbaum, Andrew S. *Operating Systems: Design and Implementation (Second Edition)*. New Jersey: Prentice-Hall 1997.
* *Intel Architecture Software Developer's Manual*–Volume 3: System Programming

## 関連項目
* ページング方式
* ページ置換アルゴリズム

## 外部リンク
* "So What Is A Page Fault?" from OSR Online （Windows固有の説明）
* "Virtual Memory Details" from the Red Hat website.
* "UnhandledExceptionFilter (Windows)" from MSDN Online.