[[PageNavi(internal24-navi)]]
{{{ comment
h2w-title:メモリ確保アルゴリズム詳細
}}}
=== メモリ確保アルゴリズム詳細 === #SECTION043122300000000000000
下記do_try_to_free_pages関数は、ユーザメモリ、バッファキャッシュなどをを検索し、利用頻度度の低いものからどんどん解放する。目的の解放数が達成できるまでの間、何度も繰り返す。
解放するとはいっても、v2.2の時とは異なりv2.4では、好きなときにいつでも解放可能なキャッシュ(INACTIVE-CLEANリストにリンクされたページ)まで落すのみで、完全なフリーページにすることはない。(そのページ上のデータと全く同じものがディスク上にも存在する状態であるため、いつそのページが別の用途に転用されても問題が生じない)
ページ解放は二段階で行われる。
1. 解放候補のページ(INACTIVE_DIRTYリスト上のページ)の解放を 試みる。(page_launder関数)
1. 現在利用中のページ(ACTIVEリスト上のページ)のうち、参照頻度の 低いものを選び出し、解放候補のページ(INACTIVE_DIRTYリスト 上のページ)、解放可能なページ(INACTIVE_CLEANリスト上のページ) とする。必要であればSWAPデバイス上にページ上のデータを吐き出す。 (refill_inactive関数)
{{{
do_try_to_free_pages()
if(空きメモリが不足) {
解放候補のページ(INACTIVE_DIRTYリスト上のページ)を
いつでも解放可能なページ(INACIVE_CLEANリスト上の
ページにする(page_launder関数)
}
if(空きメモリが不足 || 解放候補のページが少なめ) {
ディレクトリエントリキャッシュの解放(shrink_dcache_memory関数)
iノードキャッシュの解放(shrink_icache_memory関数)
利用中(ACTIVE)のメモリの解放を試みる(refill_inactive関数)
} else {
カーネル内メモリアロケータ内の解放可能な
メモリを解放する(kmem_cache_reap関数)
}
}}}
page_lander関数はその関数名の示すとおり、解放候補のページの洗濯をし、いつでも解放可能な綺麗な状態にする。いつでも解放可能な状態にするだけで、本当のフリーページに戻すようなことはしない。
{{{
page_launder()
for(解放候補リストinactive_dirty) {
if (最近参照されたページ) {
ページをACTIVE状態にする(active_listに繋ぐ)
continue
}
if (I/O中なら) {
inactive_dirtyリストに繋ぎ直す
continue
}
if (バッファ域、バッファ域にマップされたページキャッシュ) {
バッファ域の解放(try_to_free_buffers関数)
if(解放できなかったなら) {
(I/O中の場合、まだDirtyな場合など)
inactive_dirtyリストに繋ぎ直す
} else if(複数のところから参照されている)
ACTIVE状態にする(active_listに繋ぐ)
else /* ページキャッシュなら */
inactive_cleanリストに繋ぐ
} else if (ページキャッシュ) {
inactive_cleanリストに繋ぐ
} else {
ACTIVE状態にする(active_listに繋ぐ)
}
if(最初なら) {
バッファのフラッシュ(wakeup_bdflush関数)
}
}
}}}
解放候補とできるページ量が少なくなってくるとrefill_inactive関数にて、解放候補のページを作り出す。
プロセスページのスワップへの追い出し(swap_out関数)より、キャッシュ域の解放(refill_inactive_scan関数)を優先的に行う。
{{{
refill_inactive()
カーネル内メモリアロケータ内の解放可能な
メモリを解放する(kmem_cache_reap関数)
for(プライオリティを変更しつつ) {
/*swapアウトによる空きメモリの生成*/
while (refill_inactive_scan() || swap_out()) {
if(目的のページ数を解放したら) return
}
ディレクトリエントリキャッシュの解放(shrink_dcache_memory関数)
iノードキャッシュの解放(shrink_icache_memory関数)
/*共有メモリのスワップアウト*/
while (shm_swap()) {
if(目的のページ数を解放したら) return
}
if(空きメモリ量が十分になった) return
}
}}}
ページが最近参照されたかどうかを示すためにpage構造体中に参照ビット(PG_referenced)を持っており、これらキャッシュを参照する度(__find_page_nolock関数)にこのビットを立てるようにしている。refill_inactive_clean関数では、この参照ビットが立っているページはAGE(参照頻度)を最大にし解放の対象外とする。また同時に参照ビットのクリアを行う。
refill_inactive_scan関数は、参照されていない(各種キャッシュ用の)ページであれば、解放候補リスト(INACTIVEリストに繋ぎ直す)
{{{
refill_inactive_scan()
for(ACTIVEリスト上のページ) {
if(ページに参照ビットPG_referencedが立っていたら) {
ページの参照ビットPG_referencedを落す
ページのAGEを元に戻す(age_page_up_nolock関数)
} else {
ページのAGINGを行う(age_page_down_ageonly関数)
if(何処からも参照あれていないページ)
ページを解放対象ページとする(deactivate_page_nolock関数)
}
if(1ページ解放指定 && 解放成功) return;
}
}}}
----
''(NIS)HirokazuTakahashi [[BR]]2000年12月09日 (土) 23時55分06秒 JST''1
[[PageNavi(internal24-navi)]]