仮想記憶がない場合の問題点
メモリの断片化
プロセスが生成された後に、メモリの獲得、開放を繰り返すと発生
する。
メモリの領域が細かく断片化され領域の確保に失敗する。
扱うデータが領域より大きいと失敗する。
プログラム側が断片化を意識して実行するので不便。
マルチプロセスの実現が困難
-
同じプロセスを二つ同時に実行すると正しく動作しない
。 -
違うプロセス同士を同じメモリ領域で実行できない
。
これらを意識して配置場所が重ならないように意識
する必要がある。
不正な領域へのアクセス
カーネルやたくさんのプロセスがメモリ上に配置されている場合、あるプロセスがカーネルや他のプロセスに割り当てられたメモリのアドレスを指定すれば、それらの領域にアクセス
できてしまいます。
このためデータの漏洩や破壊のリスク
があります。
気づき
メモリを使い続けるとごちゃごちゃしてリスクあるのか
参考
仮想記憶
仮想記憶は、プロセスがメモリアクセスする際に、システムに搭載されているメモリに直接アクセスさせるのではなく、仮想アドレスというアドレスを用いて,間接的にアクセス
させるという機能です。
...
メモリの実際のアドレスを「物理アドレス」
...
アドレスによってアクセス可能な範囲を「アドレス空間」
と呼びます
物理アドレスを指定できない
readelfコマンドやcat /proc/<pid>/mapsの出力で記載されたアドレスは実は、すべて仮想アドレス
です。なお、プロセスから実際のメモリに直接アクセスする方法、言い換えると、物理アドレスを直接指定する方法はありません
。
気づき
前見ていたアドレスはすでに仮想アドレスだったのか。
ページテーブル
仮想アドレスから物理アドレスへの変換には、カーネルのメモリ内に保存されている「ページテーブル」
という表示を用います。CPUはすべてのメモリをページ
という単位で区切っており、アドレスはページ単位で変換
されます。
ページテーブル中の一つのページに対応するデータを「ページテーブルエントリ」
と呼びます。ページテーブルエントリには、仮想アドレスと物理アドレスの対応情報
が入っています。
...
ページテーブルを作るのはカーネル
です。...カーネルはプロセス生成時にプロセスのメモリを確保して、そこに、実行ファイルの内容をコピーすると書きました。そのときに同時に、プロセスようのページテーブルも作るのです。プロセスが仮想アドレスにアクセスした際に物理アドレスに変換するのは、CPUの仕事
です。
気づき
CPUは仮想アドレスから物理アドレスの変換を行い、仮想アドレスにアクセスされたときも物理アドレスに変換する他の部品のことなのにCPUはお世話をするのか。
カーネルは子プロセスを生成するときもプロセス専用のページテーブルを作成もするのか。
つまりページテーブルに対応されていなければアクセスできないのか。
ページフォールトハンドラ
ページテーブルが物理アドレス部分と対応していない仮想アドレスにアクセスするとページフォールト
という例外が発生します。
...
ページフォールト例外によってCPU上で実行中の命令が中断
されて、カーネルのメモリに配置されたページフォールトハンドラ
という処理が実行されます。
...
カーネルは、ページフォールトハンドラにおいて、プロセスによるそのメモリアクセスが不正なものであることを検出します。この後はSIGSEGV
というシグナルをプロセスに送信します。SIGSEGVを受信したプロセスは、通常は強制終了
させられます。
参考
ページフォールトハンドラを見てみよう
root@**********:************# go build segv.go
root@**********:************#./segv
不正メモリアクセス前
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=]
goroutine 1 [running]:
main.main()
/************/************/************/************/************/segv.go:9 +0x7b
root@**********:************## make segv-c
cc segv-c.c -o segv-c
root@**********:************## ./segv-c
Segmentation fault (コアダンプ)
気づき
エラーで終了している
仮想記憶による問題の解消の気づき
メモリの断片化
断片化していても仮想アドレスは一塊になっているよう見えるからプロセス側は楽に処理ができる
マルチプロセスの実現が困難
プロセスごとのページテーブルを作成しているので重複することはない
不正な領域へのアクセス
プロセス側から物理メモリを見ることができないから他にアドレスを指定できないから不正アクセスができない
感想
CPU、カーネルを使ってメモリの混雑状況の中うまくやっているんだな。