Swap - ページアウト
Rev.2を表示中。最新版はこちら。
1. ページアウト処理の概要
1.1 ページアウトの開始
空きメモリが少くなってkswapdがwakeupされたり、alloc_pages()でFreeListからページが取れなかった場合、Inactiveリストからページを回収して空きメモリを増やそうとする(「空きページの確保」参照)。Inactiveリストをスキャンした時にPageCacheのページは(Dirtyでなければ)解放されるだけだが、匿名ページは解放前にディスク(スワップファイル)に書き出す必要があり、ページアウト処理が発生する。
Inactiveリストのページをスキャンしてページを解放する処理はshrink_list()で行なわれる。shrink_list()のページアウトに関する処理を抜きだしたものを以下に示す。
while (!list_empty(page_list)) { : /* 匿名ページでSwapCacheに登録されていないければ、 * add_to_swap()を呼び出してページアウト先を決定する。 * 1.2節参照 */ if (PageAnon(page) && !PageSwapCache(page)) { if (!sc->may_swap) goto keep_locked; /* スワップ領域から未使用ページを取得して、SwapCacheに登録 * そして、ページをDirty状態にする */ if (!add_to_swap(page, GFP_ATOMIC)) goto activate_locked; } /* ページがユーザ空間からマップされている * (プロセスのPTEがマップされている)場合は * ユーザ空間からアンマップする。(*1) * 1.3節参照 */ if (page_mapped(page) && mapping) { switch (try_to_unmap(page, 0)) { : : case SWAP_SUCCESS: ; } } /* Dirtyページをディスクに書きだし * 1.4節参照 */ if (PageDirty(page)) { switch(pageout(page, mapping)) { : : case PAGE_SUCCESS: } } }(*1) この物理ページにマップしている仮想アドレス空間は1つとは限らない(複数のプロセスで享有されている可能性がある)。try_to_unmap()はRmapをたどり、このページにマップしている全仮想空間からアンマップする。
1.2 ページアウト先の割り当て
shrink_list()でページをスキャンしてSwapCacheに登録されていない匿名ページを見つけたら、このページはページアウト対象なので、まずページアウト先を割り当てるためにadd_to_swap()を呼び出す。
add_to_swap()はSwap空間のどのページにページアウトするかを決定する。その後、ページをSwapCacheに入れてDirty状態にする。
ページアウト先の決定はget_swap_page()で行なう。get_swap_page()は、システムに複数のSwap領域がある場合は以下のルールに基づき、まずどのSwap領域を使用するか決める。
- 空き領域のあるSwap領域の内、最も優先度の高いものを選択する
- 同優先度のSwap領域がある場合は、その中でラウンドロビンで選択する
その次に、選択したSwap領域からscan_swap_map()で空きページを探して返す。scan_swap_map()は空きページを探す際、空きページがある程度連続しているところを探して返すようにしている。このようにすることで、複数ページのページアウトが連続ディスクブロックに書き出されやすくなり性能が向上する。