デマンドロード

生成直後の仮想空間(ページ)にアクセスをすると, まだ実際には物理メモリが割り当てられていないため, CPU例外が発生する. そのときlinuxでは, do_no_page関数が呼び出される.

ファイルがマッピングされて無い領域の場合, do_anonymous_page関数を利用して, 適当な空き物理ページを割り当てる. (PTEに物理ページの物理アドレスとページ有効属性を設定する. 書き込みアクセスの場合, 書き込み可の属性も設定する)

ファイルがマッピングされている場合, filemap_nopage関数が呼び出される. このパスは, ファイルシステムの章で説明したファイル読み込み処理とほぼ同等である. ページキャッシュに目的のファイルデータが載っていない場合, そのファイルinodeのreadpageオペレーションを呼び出し, ページキャッシュに読み込む.

do_no_page(タスク、仮想空間管理構造体vm_area_struct、アドレス...)
{
        if (ファイルマップされていない領域?) {
                単純物理ページ確保とマップ(do_anonymous_page関数)
                return;
        }
        仮想空間管理構造体vm_area_structのnopageオペレーションを呼び出す。
          (ext2fsの場合は、 filemap_nopage関数)

        pteのデータを生成(mk_pte関数)
        if(書きこみアクセスか) {
                書きこみ可とする(pte_mkwrite関数)
                dirtyのビットも立てておく(pte_mkdirty関数)
        } else if (共有mmapでないが、複数のプロセスで共有している) {
                書きこみ禁止とする(pte_wrprotect関数)
                  (※これに関しては、コピーオンライトの説明を見よ)
        }
        実際のページテーブルに登録(put_page関数)
}

ファイルマップされていないページでのフォルトの場合は、下記関数において適当な空き物理ページを確保し、pteに登録する。readアクセスの時は、コピーオンライトモードでシステムに一つだけ用意したZERO_PAGEをマップしておく。

do_anonymous_page(タスク、仮想空間管理構造体vm_area_struct、....)
{
        if (writeアクセスなら) {
                空き物理ページを確保(__get_free_page関数)
                確保した物理ページを0クリア(clear_page関数)
                pteデータの作成、書きこみ可とし、(pte_mkwrite関数)
                  dirtyのビットも立てておく(pte_mkdirty関数)
        } else { /* readアクセスなら */
                pteデータの作成、システム内に一つだけ用意された0クリア
                 されたページ(ZERO_PAGE)を書きこみ禁止でマップする
                 (pte_wrprotect関数)
                  (※これに関しては、コピーオンライトの説明を見よ)
        }
        実際のページテーブルに登録(put_page関数)
}

ext2ファイルシステム上のファイルの場合、ファイルマップされたページでフォルトが発生すると、filemap_nopage関数が呼び出される。この関数はフォルトを発生させたページに対応するファイルのブロックを物理メモリ上の読み込む処理を行う。

filemap_nopage(仮想空間管理構造体vm_area_struct, アドレス, 共有mmapか?)
{
        pageキャッシュ上に無いか検索(__find_page関数)
        if(pageキャッシュ上に無い) {
                フォルトの発生したページの前後を、複数ページ分先行readする。
                (try_to_read_ahead関数) 現コンフィギュレーションでは16ページ
                if(もし、pageキャッシュ上から落ちている場合は) {
                         フォルトが発生したページを再読み込み
                           (inodeのreadpageオペレーション)
                }
        }
        if (共有mmap域なら) {
                return このページを返却
        }
        新しいページを確保し、pageキャッシュの内容をそこにコピーする(copy_page関数)
        return 新しいページ
}
img62.gif

書き込み処理でdo_no_page関数が呼び出されたときは、確保した物理ページのPTEを書き込み可にしてマップする。

readアクセスによりdo_no_pageでマップされたばかりの空間は、write禁止の状態で生成される。(ファイルからの読み込みであれば、pageキャッシュ上に登録される)この空間に対して書き込みアクセスがあると、例外が発生しdo_wp_page関数が呼び出される。

do_wp_page関数はページキャッシュ内のページであればページキャッシュから落しPTEのWビットを立て書き込み可能とする。システム共有のZERO_PAGEであれば、そのページの複製を作りPTEを書き込み可能(Wビットを立てた)にし、複製したページを登録する。

処理は、下記コピーオンライトのルーチンと共用しており、do_wp_page関数の詳細はそちらを参照のこと。

img63.gif

(NIS)HirokazuTakahashi
2000年06月11日 (日) 22時29分57秒 JST
1