OS: メモリー管理機能の仕組み

 コンピュータの動作にCPUと並んで不可欠なのがメモリーです。プログラムを実行するには、プログラムがメモリー上にロードされている必要があります。また、計算対象のデータ、入出力するデータもメモリーに置かれます。

 メモリー上のどの領域に、いつ、どのデータを載せるのかによって、プログラムの処理の効率が変わります。これを制御するのが、OSが持つメモリー管理の機能です。メモリー管理は、タスク起動時のプログラムのロード、実行中のプログラムによる動的なメモリー確保だけでなく、ファイルやネットワークなどのキャッシュ、バッファの管理でも使用されます。

 コンピュータのメモリーには、位置を特定するアドレスがついています。このアドレスをそのまま使うと、複数のプログラムが同じアドレスを使ってしまわないように、どのプログラムがどのアドレスを使うか事前に決めなければならなくなります。しかしカーネルのメモリー管理機能があるので、その必要はありません。カーネルは物理的なアドレスと仮想的なアドレスの対応付けを管理することで、すべてのプログラムが他のプログラムを意識しないでメモリーを使えるようにします。

 カーネルは、メモリーの用途別にアクセス保護を設定することで、バグや悪意による不正なメモリーアクセスからプログラムやシステム全体を保護します。不正なメモリーアクセスがあると、カーネルはそのことを示すメッセージやイベントを発生させ、プログラムを強制的に終了させます。

 ライブラリや命令が格納されたメモリーは読み取り専用で、書き込みを試みると例外になります。また、カーネルのメモリーは、カーネルのコードを実行しているとき以外は、プログラムから読み書きできないように設定します。

 ストレージI/Oは、メモリーアクセスに比べると非常に遅い操作です。そこでカーネルは、メモリーをストレージのキャッシュとして使用します。一度読み込んだストレージの内容をメモリーに保持することにより、再度同じ箇所を読み込む場合、メモリーの内容をプログラムに返す、あるいは書き込み内容をメモリー中に保持します。そして適切なタイミング、あるいはプログラムから指示されたタイミングで書き込むことにより、全体的なI/O性能を向上させます。
f:id:nonbei:20180608172820j:plain
OSのメモリー管理機能によるキャッシュへの書き込みと読み込み


 キャッシュは、プログラムが読み書きするファイルだけでなく、ライブラリを含むプログラムの命令部分にも使われます。

使用中のキャッシュを回収
 メモリーをプログラムの命令とデータ、およびファイルI/Oのキャッシュとして際限なく使い続けると、いつかは空きメモリーがなくなります。そこで、OSは、空きメモリーを監視し、一定の基準に基づき、使用されていたメモリーを回収し、空きメモリーにします。メモリーとストレージの内容が同じキャッシュは、直ちに空きメモリーにしても、後に再度ストレージI/Oを行う必要があるにしても、システムの正常な状態を損ないません。

 また、更新されたキャッシュは、ストレージに更新内容を書き戻せば、回収できます。これに対し、プログラム中のデータ領域やヒープ領域(動的に割り当てたデータ領域)は、対応するストレージの内容がありません。このようなメモリーを回収する必要がある場合、OSは、スワップ領域あるいはスワップファイルにメモリーの内容を書き出して、対応するメモリーを回収します。

 メモリー監視ツールが報告する空きメモリーを見るとき、どのメモリーを空きメモリーと報告するかに注意が必要です。一般に空きメモリーとして表示されるのは何にも使われていないメモリーであり、回収可能なキャッシュは含まないことが多いからです。使用中のメモリーには回収可能なキャッシュが含まれるので、空きメモリーが少ないからといって、システムが危機的な状況にあるとは言えません。

 空きメモリーが少ないのを問題視し、強制的にキャッシュを回収させたり、キャッシュのサイズを制限すると、不必要なストレージI/Oでシステム全体の性能を低くださせるリスクもあります。メモリーの使われ方はさまざまであり、監視方法についても一つの正解を示すことはできません。ただしよく使われる指針としては、継続的なスワップの発生を深刻な問題の兆候として監視します。