空間の複製

仮想空間の複製は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ビットオフ)としてマップし直す。

img64.gif

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