仮想アドレス空間管理
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2021/07/07 02:02 UTC 版)
各プロセスの仮想アドレス空間には、そのプロセスが使用するコードやデータが配置される。ページング方式であれ、セグメント方式であれ、仮想アドレス空間内で使用している範囲の管理と制御が仮想記憶機構として必須である。例えば、実行ファイルの内容を仮想メモリ上に配置する領域、スタックを配置する領域などがある。このような領域をセグメントと呼ぶ。セグメント方式のセグメントと似ているが、純粋に仮想的なオブジェクトである。実行ファイルを配置する領域は必ずしも連続ではない。プログラムのコード部分とデータ部分を分離して配置するのが一般的で、前者をテキストセグメントもしくはコードセグメント、後者をデータセグメントと呼ぶ。Unix系システムや Windows では、一般的にデータセグメントの一部としてBSSセクションとヒープ領域を含む。BSSセクションにはプロセス起動時に0に初期化される静的変数を配置する。初期値が0の静的変数を別扱いしているのは、読み書きが発生するまで0で初期化するのを後回しに出来るようにするための高速化のテクニックである。Unix系システムではヒープ領域はデータセグメントの末尾に配置され、brk() 関数などでデータセグメントのサイズを変えることでヒープ領域のサイズを変えられるようにする。各セグメントはマッピングしているオブジェクトが何であるか、その領域へのアクセス権などを属性情報として保持する。 テキストセグメントはファイルシステム上の実行ファイルの一部と完全に対応しており、書き換えられることもない。従って、マッピングしているオブジェクトは実行ファイルであり、アクセス属性は「リードオンリー」となる。データセグメントやスタックは一時的な存在であるため何かをマッピングしているわけではない。そこでこれらは匿名ファイル(Anonymous File)をマッピングしているものとして管理される。匿名ファイルをマッピングしているセグメントに対応するページを匿名ページと呼び、これがスワッピングの際にスワップ領域に書き出される。データセグメントは当初は実行ファイルの一部と対応しているが、書き込み可能な属性が設定されている。ページング方式の場合、データセグメント内の内容が更新されたページはページ単位で匿名ページへと属性変更される。 exec() システムコールなどで新たにプロセスの仮想アドレス空間を設定した当初は、基本的にこのような仮想アドレス空間を管理するデータ構造がカーネル内に作成されるだけで、実際の実行ファイルの内容はロードされない。Unix系システムでは、exec() システムコールからユーザ空間に制御が戻された瞬間にページフォールトが発生し、そこで初めてページ単位に実行ファイルの内容がロードされる。ただし、性能向上目的で事前にマッピングを作成する場合もある。 各プロセスの仮想アドレス空間のアドレス範囲は同じでありオーバーラップしているのが一般的である。これを多重仮想記憶と呼ぶ。MMUは現に実行中のプロセスの仮想空間のみを認識する。コンテキストスイッチでプロセスを切り替える際、MMUに対して仮想アドレス空間の切り替えも指示する必要があるが、その方式はアーキテクチャによって様々である。 同じプログラムを実行するプロセスが複数存在する場合、多重仮想記憶ではそれぞれが同じ仮想アドレスに実行ファイルをマッピングしていながら、それぞれ独立した仮想空間を使用する。このため、実行ファイルを配置する仮想アドレスはどのプロセスでも同じにすることができ、実行ファイル自体に配置すべきアドレスを格納しておくようになっているのが一般的である。また、それぞれのプロセスが実行ファイルのテキストセグメントをマッピングするのに使う物理メモリは共有することができる。他にも mmap() でファイルをマッピングする場合や共有メモリ機能でプロセス間の通信を行う場合、マッピングされる物理メモリが共有される。 なお、アーキテクチャによっては、多重仮想記憶がオーバーラップしていると捉えず、全仮想空間がフラットに並んだ巨大な仮想空間を想定することもある。この場合、仮想空間識別番号が巨大な仮想空間のアドレスの一部と考えられる。もっとも、これは単にモデル化の手法が違うだけで実装に大きな違いがあるわけではない。実際、各ユーザープロセスが自分の仮想空間識別番号以外の仮想空間にアクセスすることはできない。
※この「仮想アドレス空間管理」の解説は、「仮想記憶」の解説の一部です。
「仮想アドレス空間管理」を含む「仮想記憶」の記事については、「仮想記憶」の概要を参照ください。
- 仮想アドレス空間管理のページへのリンク