空きページの確保
Rev.9を表示中。最新版はこちら。
1. 概要
空きメモリが少なくなってくると、ディスクキャッシュ等のページを解放して空きメモリを増やす。
2. 処理の流れ
キャッシュの解放は主にshrink_*の関数で行われる。各関数の関連は図1のようになっている。
(注) zone_reclaim()については、NUMAアーキテクチャでなければ(CONFIG_NUMA未定義)なら何もしない。よって、get_page_from_freelist()でフリーリストからページが取れなくてもzone_reclaim()によってページの回収処理は動かない。一般的なアーキテクチャではget_page_from_freelist()が失敗した後、try_to_free_pages()でページの回収が行なわれる。
3. shrink処理の開始契機
図1にもあるようにshrink処理の開始契機となるのは以下の関数。- kswapd()
- alloc_pages()
- get_page_from_freelist() (NUMAのみ)
3.1 kswapd()
空きメモリが少なくなりkswapd()がWakeupされると(kswapdはカーネルスレッド)、balance_pgdat()を呼び出してshrink処理を開始する。
3.2 alloc_pages()
ページ割当て時に割当てできなかった場合にtry_to_free_pages()を呼び出してshrink処理を開始する。
3.3 get_page_from_freelist()
CONFIG_NUMAが定義されていれば、ページ割当て(alloc_pages())でページをFreeListから取り出す時に、空きメモリ量がWaterMarkを下回っていた場合に、zone_reclaim()を呼び出してshrink処理を開始する。通常のアーキテクチャでは、ページを取得できなかった場合は何もせずリターンする。
4. 各関数の説明
4.1 shrink_cache()
指定ZoneのInactiveリストのページを幾つか解放する。
Uptodate状態のPageCacheのページなどは単純に解放されるだけだが、Dirty状態のものはディスクに書き出す必要があるのでI/Oが発生する。また、匿名ページ(Anonymous Page)は、Swap対象となる(SwapCacheに入れられ、Dirty状態)。
解放処理自体はshrink_list()で行っている。
4.2 refill_inactive_zone()
Activeリストのページを幾つかInactiveリストに移動する。
4.3 shrink_slab()
Active,Inactiveリストのページ以外のメモリを解放する。この関数は、shrinker_listリストに登録されたshrink用ハンドラを呼び出すだけ。
現在ハンドラとしてはinodeキャッシュなどのファイルシステム関連のメモリオブジェクトの解放ルーチンが登録されている。
4.4 shrink_zone()
指定ZoneのLRUリストのページを解放して空きメモリを確保する。refill_inactive_zone()でページをInactiveリストに移動して、shrink_cache()でページを解放させている。
4.5 try_to_free_pages()
4.6 zone_reclaim()
指定Zoneから指定ページ数(2^nで指定)を回収する。CONFIG_NUMA未定義時は空の関数(return 0)となる。
scan_controlの優先度を上げながらshrink_zone()を呼び出して、ページを解放させていく。(優先度が上がるとshrink_zone()以下でスキャンするページ数が多くなるのでよりたくさんのページが回収されやすくなる)
shrink_zone()でも必要ページ数を回収できなかった場合は、shrink_slab()でさらにページを回収しようとする。