誰でもわかるメモリ管理入門:02

*この投稿は[誰でもわかるメモリ管理入門:01](https://qiita.com/segavvy/items/9a9f8aa5cc4e6760307a)の続きです。はじめての方は先に[そちら](https://qiita.com/segavvy/items/9a9f8aa5cc4e6760307a)をご覧ください。*

#お金をかけずに部屋を増やす

大家さんは気づきました。住人は外出で部屋を空けていたり、部屋にいても寝ていてなにもしていない時間が結構あります。たとえば1号室から4号室の4部屋に注目した場合、次のような感じでした。

|部屋<br/>番号| 住人       | 朝 | 昼    | 夜 | 夜中 |
|:----:|:---------:|:--------:|:------:|:------:|:----:|
|1|![Aさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/56a27719-9ada-f7bc-1e4e-8b64b301cec8.png)<br/>A|![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![外出.png](https://qiita-image-store.s3.amazonaws.com/0/139624/507edff5-3fe0-1abe-4c3b-9edf09259e19.png)|![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![睡眠.png](https://qiita-image-store.s3.amazonaws.com/0/139624/bfdf8d51-8a5d-3b2c-ee3a-1ba9c6c9c68c.png)|
|2|![Bさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/7040bfd7-8fe6-3f2a-e39f-5d19c5d11ba7.png)<br/>B|![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![睡眠.png](https://qiita-image-store.s3.amazonaws.com/0/139624/bfdf8d51-8a5d-3b2c-ee3a-1ba9c6c9c68c.png)|![睡眠.png](https://qiita-image-store.s3.amazonaws.com/0/139624/bfdf8d51-8a5d-3b2c-ee3a-1ba9c6c9c68c.png)|
|3|![Cさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/b3b527d7-668b-d407-7003-edbe1f1a98ca.png)<br/>C|![睡眠.png](https://qiita-image-store.s3.amazonaws.com/0/139624/bfdf8d51-8a5d-3b2c-ee3a-1ba9c6c9c68c.png)|![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![外出.png](https://qiita-image-store.s3.amazonaws.com/0/139624/507edff5-3fe0-1abe-4c3b-9edf09259e19.png)|![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|
|4|![Dさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/92c371df-7270-589e-4dbb-9fc62f71bffe.png)<br/>D|![睡眠.png](https://qiita-image-store.s3.amazonaws.com/0/139624/bfdf8d51-8a5d-3b2c-ee3a-1ba9c6c9c68c.png)|![外出.png](https://qiita-image-store.s3.amazonaws.com/0/139624/507edff5-3fe0-1abe-4c3b-9edf09259e19.png)|![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|

こうやって見ると、半分くらいの時間は部屋が空いているか、中にいても寝ているだけの状態です。だったら、そういった時間を他の人に使わせることで、部屋をもっと有効活用できないかと考えました。

|部屋<br/>番号| 朝 | 昼    | 夜 | 夜中 |
|:----:|:--------:|:------:|:------:|:----:|
|1|![Aさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/56a27719-9ada-f7bc-1e4e-8b64b301cec8.png) A<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Cさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/b3b527d7-668b-d407-7003-edbe1f1a98ca.png) C<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Dさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/92c371df-7270-589e-4dbb-9fc62f71bffe.png) D<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Dさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/92c371df-7270-589e-4dbb-9fc62f71bffe.png) D<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|
|2|![Bさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/7040bfd7-8fe6-3f2a-e39f-5d19c5d11ba7.png) B<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Bさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/7040bfd7-8fe6-3f2a-e39f-5d19c5d11ba7.png) B<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Aさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/56a27719-9ada-f7bc-1e4e-8b64b301cec8.png) A<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Cさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/b3b527d7-668b-d407-7003-edbe1f1a98ca.png) C<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|

こんな感じで詰め込めば、住人は4人いても半分の2部屋で済んでしまいますので、倍の人に貸せるようになりそうです。

外出で空いている時間は、その部屋を他の人に使わせてしまいましょう。住人が帰ってくるまでに元どおりに戻しておけば問題ありません。寝ている人も、起きないようにそっと部屋の外に移動して他の人に使わせましょう。起きるまでに戻しておけば大丈夫です。部屋はみんな同じ間取りなので、部屋が変わってもきっと気づかないはず。

大家さんの妄想は続きます。

#荷物をどうするか

外出中の部屋や、寝てる人をどかして空けた部屋を他の人に使わせるにしても、部屋には荷物が残っています。これらをどこかに移動しておいて、帰宅や起きるまでに戻さないといけません。そのため、一時的な荷物の置き場として倉庫を利用することにしました。倉庫なら安く拡張できるためです。

例えば1つ目の部屋は、朝から昼に変わる時に、Aさんの部屋からCさんの部屋へ切り替える必要があります。

|部屋<br/>番号| 朝 |→| 昼    |→|
|:----:|:--------:|:------:|:------:|:------:|
|1|![Aさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/56a27719-9ada-f7bc-1e4e-8b64b301cec8.png) A<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|Aさんの部屋から<br/>Cさんの部屋へと<br/>切り替える作業|![Cさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/b3b527d7-668b-d407-7003-edbe1f1a98ca.png) C<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|…|

大家さんは、Aさんの荷物を倉庫へ運び出し、Cさんの荷物を倉庫から運び入れて、Cさんが最後に外出した時の状態に戻す形になりますね。

![荷物の入れ替え.png](https://qiita-image-store.s3.amazonaws.com/0/139624/c04af96f-fdd8-5909-a3a6-aa81df286ad2.png)

ちょっと大変そうですが、この作業は[前回ご説明したファイルの管理](https://qiita.com/segavvy/items/9a9f8aa5cc4e6760307a#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E7%AE%A1%E7%90%86)とあまり変わらないので、大家さんにとっては朝飯前です。

#部屋番号をどうするか

この仕組みだと、住人が知らないうちに部屋が変わっていることになります。例えば下の表のように部屋を使い回す場合、朝に1号室を使っていたAさんは、昼に外出して夜に帰ってきたら2号室を使うことになります。

|部屋<br/>番号| 朝 | 昼    | 夜 | 夜中 |
|:----:|:--------:|:------:|:------:|:----:|
|1|![Aさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/56a27719-9ada-f7bc-1e4e-8b64b301cec8.png) A<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Cさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/b3b527d7-668b-d407-7003-edbe1f1a98ca.png) C<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Dさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/92c371df-7270-589e-4dbb-9fc62f71bffe.png) D<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Dさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/92c371df-7270-589e-4dbb-9fc62f71bffe.png) D<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|
|2|![Bさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/7040bfd7-8fe6-3f2a-e39f-5d19c5d11ba7.png) B<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Bさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/7040bfd7-8fe6-3f2a-e39f-5d19c5d11ba7.png) B<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Aさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/56a27719-9ada-f7bc-1e4e-8b64b301cec8.png) A<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|![Cさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/b3b527d7-668b-d407-7003-edbe1f1a98ca.png) C<br/>![活動中.png](https://qiita-image-store.s3.amazonaws.com/0/139624/09e05c6e-7317-7513-a32e-25d7c843076c.png)|

でも1号室に住んでいると思っているAさんは、帰ってきたら1号室に向かってしまいDさんと鉢合わせてしまいます。これはうまくありません。そこでアパートにフロントを用意し、帰ってきた時はフロントに立ち寄ってもらうことにしました。

Aさんが夜に帰ってきてフロントに立ち寄ったら、大家さんは何食わぬ顔してAさんを2号室へ案内するわけです。部屋は1号室から2号室に変わっていますが、部屋の中の荷物は出かけた時のままが復元されていますので、きっとAさんは気づきません。

大家さんは下のような住人の名前と部屋番号の対応表を管理して、部屋をやりくりする感じになります。

|住人|朝の<br/>部屋番号|昼の<br/>部屋番号|夜の<br/>部屋番号 |夜中の<br/>部屋番号 |
|:----:|:-------:|:-----:|:------:|:------:|
|![Aさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/56a27719-9ada-f7bc-1e4e-8b64b301cec8.png)<br/>A|1号室|（なし）|2号室|（なし）|
|![Bさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/7040bfd7-8fe6-3f2a-e39f-5d19c5d11ba7.png)<br/>B|2号室|2号室|（なし）|（なし）|
|![Cさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/b3b527d7-668b-d407-7003-edbe1f1a98ca.png)<br/>C|（なし）|1号室|（なし）|2号室|
|![Dさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/92c371df-7270-589e-4dbb-9fc62f71bffe.png)<br/>D|（なし）|（なし）|1号室|1号室|

#複数の部屋を借りる人はどうするか

フロントに立ち寄る方法にすれば、住人は部屋番号を覚えておく必要がありません。大家さんが顔を覚えていて部屋まで案内してくれるからです。でも、実際には1人の住人がいくつも部屋を借りることの方が多く、住人自身が自分の借りている部屋を区別するために部屋番号が必要です。そのため住人には、架空の部屋番号を知らせておくことにしました。実際に使う部屋は住人が気づかないところで大家さんが切り替えますから、部屋番号はなんでも良いのです。

住人は連続する部屋番号を借りたがります（後述しますが、プログラムがメモリを確保する場合、領域が連続している必要があるのです）。そのため、架空の部屋番号は、どの住人も1号室から順番に割り振ることにしました。例えばAさんに5部屋、Bさんに2部屋、Cさんに3部屋貸す場合、住人には次の部屋番号の部屋を貸していると思わせます。

|住人|貸している部屋数|貸している部屋の番号（架空）|
|:----:|:-------:|:-------:|
|![Aさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/56a27719-9ada-f7bc-1e4e-8b64b301cec8.png)<br/>A|5部屋|1号室〜5号室|
|![Bさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/7040bfd7-8fe6-3f2a-e39f-5d19c5d11ba7.png)<br/>B|2部屋|1号室、2号室|
|![Cさん.png](https://qiita-image-store.s3.amazonaws.com/0/139624/b3b527d7-668b-d407-7003-edbe1f1a98ca.png)<br/>C|3部屋|1号室〜3号室|

大家さんは住人の顔を覚えているので、住人間では部屋番号が重複していても何も問題はありません。所詮は架空の部屋番号です。

住人を騙していることになるのでちょっと心が痛みますが、これも部屋を増やさずに家賃収入を増やすため。大家さんはこのアイデアを実行に移すことにしました。こうして出来上がったのが「仮想記憶」と「メモリ スワッピング」という仕組みです。

#例えの整理
ここまでの例えを整理します。前回の表に、今回出てきたものを追加しました（前回と左右を逆にしてみました）。

| 例え       | 実際 |
|:-----------------:|:------------------:|
| 賃貸アパートの大家さん|OS|             
|アパートの部屋|メモリ| 
|倉庫|ファイル|
|部屋を借りる住人|プログラム|
|荷物|プログラムが使うデータ|
|部屋の中での生活|プログラムの処理|
|:new: 架空の部屋番号を割り振るアイデア|仮想記憶|
|:new: 実際の部屋番号|メモリの物理アドレス|
|:new: 大家さんが住人に割り振る架空の部屋番号|メモリの仮想アドレス|
|:new: 外出している住人や寝ている住人の荷物を倉庫に運んで部屋を空けたり戻したりするアイデア|メモリ スワッピング|
|:new: 大家さんが外出している住人や寝ている住人の荷物を倉庫に運んで部屋を空ける作業|スワップ アウト|
|:new: 大家さんが倉庫に運んでいた住人の荷物を部屋に戻して元どおりにする作業|スワップ イン|
|:new: 倉庫によけた住人の部屋の荷物|スワップ ファイル<br/>／スワップ パーティション|

今回追加した専門用語は、今はまだ気にしないでも大丈夫です。

#今回のポイント

大家さんのアイデアで重要なポイントは次の2つです。

## 搭載メモリよりも大きなメモリが使える（メモリ スワッピング）

大家さんのアイデアのおかげで、住人は実際の部屋数よりも多くの部屋を借りることができます。例えば4GBしか搭載されていないマシンでも、1GBのメモリを使うプログラムが5本以上動きます。このメモリスワッピングという仕組みは非常に便利ですが、倉庫との往復が頻繁に起きるとパフォーマンス低下の問題がでてきます。この辺は次回以降にまとめます。

## メモリの連続領域が確保しやすくなる（仮想記憶）

メモリを確保するプログラムを書くと、そのメモリ領域はアドレスが連続する形で確保されます。書き方は言語によりますが、例えば`malloc(8192)`とか`new long[1024]`などで8KBのメモリを確保する場合、アドレスが連続する8KB分のメモリ領域が確保される形です。もし合計で8KBのメモリが空いていても、そのアドレスが連続していなければエラーになったり例外が飛んだりして失敗します。C/C++などのアドレスを扱う言語をお使いの方は、メモリ確保した時に、そのアドレスが途中で飛んでいたらプログラムが書けなくなってしまうことがお判りいただけるかと思います。確保するメモリのアドレスは連続している必要があるのです。

メモリを確保する時にアドレスが連続していないといけない制限は、断片化と呼ばれるやっかいな問題を起こします。
部屋の例えではなくなってしまいますが、電車に5人掛けの椅子があったと時、その真ん中に人が座ってしまうと、あと４人座れるのに3人並び（＝アドレスが連続する）の確保すらできません。

![連続した席がない.png](https://qiita-image-store.s3.amazonaws.com/0/139624/66e41b98-f0a3-2efb-a212-886b3fda6dbe.png)

これがメモリの断片化と言われる現象で、あるプログラムが席の真ん中に座ってしまうことにより、席は空いているのに他のプログラムが座れなくなってしまう問題です。

そこで、大家さんの架空の部屋番号のように、OSは個々のプログラムには実際のアドレスを知らせず、個々のプログラムごとに独立した架空のアドレスを知らせ、OSが架空のアドレスと本物のアドレスを読み替えて処理します。こうすることで、実際のメモリのアドレスは連続していなくても、プログラムから見ると他のプログラムに邪魔されない連続したアドレスのメモリを確保できるようになり、プログラムを書く人を困らせずに、メモリを効率的に活用できるようになります。

（なお、この仕組みで解消するのは、あくまでも他のプログラムによって邪魔されることによるメモリの断片化です。自身のプログラム内でもメモリ断片化の現象は発生します。この辺のお話は、もしこのメモリ管理入門が長続きするようであれば触れてみたいと思います。）


今回は以上です。次回の[誰でもわかるメモリ管理入門:03](https://qiita.com/segavvy/items/41ed6042a2341a8e03b4)では、新たに大家さんがひらめいた倉庫の往復を減らすためのアイデアや、部屋が足りなくなってしまった時に起きることなどについてまとめます。
![大家さんのひらめき.png](https://qiita-image-store.s3.amazonaws.com/0/139624/7cfd1190-3f3d-b8a3-07d8-bda44b6bf8ee.png)