fork()関数の高速化
fork()関数発行時には、親プロセスのメモリを子プロセスにすべてコピーするのではなく、ページテーブルだけをコピー
します。
....
その後にメモリを読むと、親子ともに共有された物理ページにアクセスできます
。
一方親子のいずれかがデータを更新使用すると、ページの共有を解除して、それぞれのプロセスは専用のページを持つ
ことになります。
データの更新の流れ
- 書き込み権限がないので、CPU上で
ページフォールトが発生
。 - CPUがカーネルモードに遷移して、カーネルのページフォールとハンドラが動き出す。
- ページフォールトハンドラは、アクセスされたページを別の物理メモリ上にコピーする。
- 親子プロセスともに、
子プロセスが更新しようとしたページに対応するページテーブルエントリを書き換える
。親プロセスのエントリは、書き込み権限を有効化する。子プロセスは先の処理でのコピー先の領域を参照
する
コピーオンライト(CoW)
fork()関数の発行時にではなく、その後の発生する各ページへの初回書き込み時にデータをコピーする
ため、この仕組みをコピーオンライトと呼びます。
気づき
変更するページだけメモリを使用するので増加分が少なくて済む。
共有メモリはすごい。
共有メモリのおかげで物理メモリ以上のプロセスを動かすことができる。
プロセスが生成された後も、それぞれのメモリが全メモリにwriteすることは極めて稀なので、システム全体のメモリ使用量も減らせる
。とはプロセスの仮想メモリがメモリ使用中の全プロセスに対して書き込む作業が稀ということなのか?それは分からなかった。
コピーオンライトを見てみる
root@*******:************# ./cow.py
*** 子プロセス生成前 ***
freeコマンドの実行結果:
total used free shared buff/cache available
Mem: 3907956 971248 1543992 5408 1392716 2686232
Swap: 1190340 0 1190340
親プロセスのメモリ関連情報
RSS MAJFL MINFL
112256 2 27083
*** 子プロセス生成直後 ***
freeコマンドの実行結果:
total used free shared buff/cache available
Mem: 3907956 972552 1542480 5408 1392924 2684852
Swap: 1190340 0 1190340
子プロセスのメモリ関連情報
RSS MAJFL MINFL
110076 1 618
気づき
usedが1MB増えている。
RSSが2MBぐらい減っている。これは理由はわからない。
*** 子プロセスによるメモリアクセス後 ***
freeコマンドの実行結果:
total used free shared buff/cache available
Mem: 3907956 1076628 1438404 5408 1392924 2580828
Swap: 1190340 0 1190340
子プロセスのメモリ関連情報
RSS MAJFL MINFL
110088 1 26648
気づき
usedがさらに100MB増えている。ここで書き換えられたのか。新たに割り当てられている。
出典
感想
難しかくなってきた。
とりあえず頑張ろう。
メモリの使用量が共有メモリのおかげで節約できている