私は仮想メモリに関する教科書を読んでいましたが、次のように言いました。
すべてのLinuxプログラムは、以下を実行する関数を呼び出してローダーを呼び出すことができますexecve
。
現在のプロセス仮想アドレスのユーザー部分から既存のゾーン構造を削除します。
新しいプログラムのコード、データ、bss、およびスタック領域の新しい領域構造を作成します。これらすべての新しい分野は個人書き込み中のコピー。コードとデータ領域は、a.out ファイルの .text セクションと .data セクションにマップされます。
fork()
私は、プログラムが単一プロセスプログラム(使用されていない)である場合、この単一プロセスが仮想アドレス、つまり.data
その一部から始まると、a.out
保護エラーが発生し、エラーハンドラが保護例外が発生したことを認識すると思いました。プライベート書き込み時間コピー領域のページに書き込もうとするプロセスが原因で、物理メモリにページの新しいコピーが作成されます。
これには2つの問題があります。
物理メモリに同じページを共有するための2番目のプロセスがない場合でも、プライベート領域の書き込み中にコピーメカニズムはまだ新しいページを作成します。これは、プロセスが1つしかなくプロセスがないため、まったく役に立ちません。他のプロセスは新しいページを生成します。このページに書き込むと、プロセスがページを変更しようとするたびに処理のために例外が発生します。これは非常に非効率的ですか?
ページの新しいコピーが物理メモリに作成されると、プロセスで参照されなくなった元のページはどうなりますか?前のページが物理メモリにある場合、メモリの無駄ではありませんか?
答え1
重要な情報がありません。カーネルが書き込み中のコピーシナリオに対応するページエラーを処理するときに、ターゲットページが単一のプロセスで使用される場合、ページをコピーするのではなく書き込み可能にします。
カーネルは各ページのカウンタを保持します。mapcount
存在するstruct page
;単一プロセスがページをマッピングする場合、このカウンタはゼロであり、新しいプロセスがページをマッピングするたびに増加し、マッピングが解放されると減少します(例えば書き込み中のコピーであり、プロセスが書き込みを試みるからです。