Linuxカーネルに関する技術情報を集めていくプロジェクトです。現在、Linuxカーネル2.6解読室の第2章までを公開中。
仮想空間の複製はdup_mmap関数にて行う. この関数はforkシステムコールでのみ利用される.
この関数では、仮想空間の複製のみを行うが、物理メモリの複製は行わず二つの空間で共有させる。物理メモリの複製はどちらかの仮想空間に対し、書きこみがあるまで遅延させる。
その実現のため、二つの仮想空間のPTEにおいて書きこみ禁止モード(コピーオンライトモード)にしておく。書きこみ禁止であっても、この空間に対する読み込み処理は可能である。
dup_mmap(メモリ管理構造体mm_struct) { for (カレントプロセスのmm_structに登録されている全ての仮想空間管理構造体vm_area_structに対して) { 新しい仮想空間管理構造体vm_area_structを確保 カレントの仮想空間管理構造体vm_area_structの情報を、 新しい仮想空間管理構造体vm_area_structにコピー 新しい仮想空間管理構造体vm_area_structを、引数で渡された メモリ管理構造体mm_structに登録 if(ファイルマップされた仮想空間域なら) { 一つのファイルを共有しているしていることを管理する ため、仮想空間管理構造体をvm_area_struct相互にリンクしておく } PGD,PTEをコピー(copy_page_range関数)。 } }
この関数ではPTEのみのコピーのみをおこない、ページの実体コピーは行わない。空間が個別マップで、かつ書きこみ可能ならコピーオンライトモードでマップする.
copy_page_range(コピー先メモリ管理構造体vm_area_struct、 コピー元メモリ管理構造体vm_area_struct、 仮想空間管理構造体) { コピー元の先頭PGDを求める(pgd_offset関数) コピー先の先頭PGDを求める(pgd_offset関数) for(仮想空間のある間、全てのコピー元PGDに対し) { if (コピー元のPGDが空)continue if (コピー先のPGDが空) PMDテーブルを確保、登録(pmd_alloc関数) コピー元のPGDが指す先頭PMDを求める(pmd_offset関数) コピー先のPGDが指すPMDを求める(pmd_offset関数) for(コピー元PGD内の全てのPMDに対し) { if (コピー元のPMDが空)continue if (コピー先のPMDが空) PTEテーブルを確保、登録(pte_alloc関数) コピー元のPMDが指す先頭PTEを求める(pte_offset関数) コピー先のPMDが指すPTEを求める(pte_offset関数) for(コピー元PGD内の全てのPTEに対し) { if (コピー元のPTEが空)continue if (PTEが有効でない(!pte_present関数) ) { スワップ参照数を1増やす (swap_duplicate関数) コピー元のPTEの内容をコピー先のPTEに 複製(set_pte関数) contnue } if (個別マップ、かつ書きこみ可能の空間) { コピー元のPTEの書き込み可のビットを 落とし(pte_wrprotect関数)、コピー元の PTEに下記戻しておく(set_pte関数) } if (共有モードでの複製なら) { PTEからdirtyビットを落とす(pte_mkclean関数) } PTEにアクセスビットを立てる(pte_mkclean関数) コピー先のPTEにコピー(set_pte関数) } } } }
下図のように、書き込み可能なページをマップするPTEも全て、書き込み不可(Wビットオフ)としてマップし直す。
(NIS)HirokazuTakahashi
2000年12月09日 (土) 23時55分06秒 JST1
[ページ情報]
更新日時: 2008-08-27 14:18:17, 更新者: hiromichi-m
[権限]
表示:無制限, 編集:ログインユーザ, 削除/設定:メンバー