メモリの世界観です。ハードウェア1(半導体)も参照のこと。
メモリは、コンピュータの中でデータを記憶するための素子のこと。
メモリの特徴は、
・メモリの中の記憶情報の格納場所(番地・住所)を指すメモリアドレスを指定して読み書きする。x86のアセンブリ言語ではmov XX [XX]を使う。
・CPUの計算に使われるレジスタより低速。
・電源を消しても内容を保持できるハードディスクなどの磁気ディスクより高速。
CPUとメモリは密接な関係にある。CPUのレジスタで計算した内容をメモリに記憶させ、メモリで記憶した内容をCPUのレジスタに読み込むことで、すべてのコンピュータのプログラムは動いている。
2023.05.18編集
メモリは基本的に、0と1を記録しておくデバイス。0と1の情報のことを「ビット」と言う。また、ビット1つ分の情報を「1ビット」と呼ぶ。
メモリは8ビットずつまとめて扱う場合が多く、8ビットのことを「1バイト」と呼ぶ。
メモリ操作では、このバイトごとにアドレス(値の存在する番地)がふられ、アドレスから値を見ることができる。
(ふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道を参考に執筆しました。)
Intelの16ビットCPUでは、レジスタを16ビットで管理する。レジスタの値は上位8ビットと下位8ビットに分けられる。AXレジスタならAHとALに分割される。
また、アドレスの番地を示すために「セグメント」の考え方を用いる。セグメントアドレスは具体的な値(たとえば32CEなど)に固定され、これにオフセットアドレス(たとえば0100)を加えた値になる。
マシン語でプログラミングを行う際、オフセットアドレスは昔のプログラミング言語でいう行番号のように使うことができ、ジャンプ命令などではオフセットアドレスを指定してジャンプできる。
MOV命令でオフセットアドレス[0201]にALレジスタの値を格納するにはMOV [0201], ALとすればよい。
この時、物理アドレスは、「セグメントアドレス + オフセットアドレス = 物理アドレス」のようになる。
(はじめて読む8086―16ビット・コンピュータをやさしく語る (アスキーブックス)を参考に執筆しました。)
CPUのステージのひとつである実効アドレス計算では、アドレスの指定方式(アドレッシングモード)に応じて(たとえば直接あるいは間接的にアドレスを指定したり、アドレスにレジスタの値を加えた相対位置から指定したりする)、実際のメモリアドレスを計算する。
アドレス修飾には、即値アドレス指定、直接アドレス指定、間接アドレス指定、相対アドレス指定、インデックスアドレス指定、ベースアドレス指定がある。
指定方法 | 説明 |
---|---|
即値アドレス指定 | アドレス部にデータを直接指定する。 |
直接アドレス指定 | アドレス部にデータの格納されているアドレスを指定する。 |
間接アドレス指定 | アドレス部にアドレスを指定し、その参照した先にさらにアドレスが格納されている。 さらに何重にも行う場合がある。 |
相対アドレス指定 | アドレスに命令アドレスレジスタ・プログラムカウンタの値を加える。 |
インデックスアドレス指定 | アドレスにインデックスレジスタの値を加える。 |
ベースアドレス指定 | アドレスにベースレジスタの値を加える。 |
インデックスレジスタは、たとえば配列などの順次処理でインデックスを表すのに使用する。ベースレジスタはデータの基準となる場所を表し、ベースレジスタの値を変えることでプログラムがどこにあっても参照できる。
以下は参考文献。
(計算機アーキテクチャ (情報工学入門選書)を参考に執筆しました。)
仮想記憶とは、メモリを物理アドレスと論理アドレスに分け、論理アドレスを物理アドレスに翻訳することで、実際よりも多くのメモリ領域を利用可能とし、またほかのプログラムの使用するメモリ領域を気にすることなくプログラムを記述することができるようにする機能。
仮想記憶の管理はオペレーティングシステムが行う。
すべての仮想記憶を主メモリに置くのではなく、一部を主メモリ上に、一部をストレージディスク上に置く。
主メモリとディスクの入れ替えの際の単位として、ページ方式とセグメント方式がある。ページ方式では、一定のサイズ(たとえば4KB)ごとに分割する。これに対してセグメント方式は、意味のある論理的なまとまり(セグメント)に分割する。
RAMはデータの読み書きが出来るメモリ。反対に読み込みしかできないメモリをROMという。
後日注記:ランダムアクセスとは、「必要な時に必要な場所にアクセスできる」という意味で、初期のメインフレームなどに多かったシーケンシャルアクセス(一件目から順番にしかアクセスできない、たとえばテープなど)の対義語だが、電源を落としてもデータが消えないROM(あらかじめ記録された情報を読み出しするだけが可能)に対して、RAMは電源を落とせばデータが消えてしまうという意味で使われることも多い。
後日注記:昔のBASICマシンなどでは、小型のBASICインタプリタをROMで搭載し、最初から変わらずに読み込まれるようにしていた。それによってBASICプログラムを記述して実行することができた。ROMはこのように、変わらずに同じものを読み込むような、最初から搭載されているプログラムのために使われることが多い。
Wikipedia
主記憶装置に用いられる。安価で容量が大きい一方、SRAMと比較すると低速。
後日注記:DRAMは記憶素子の回路が単純であるため集積することが容易である。なので大容量にすることができる。
(放送大学「コンピュータの動作と管理 ('17)」を参考に執筆しました。)
Wikipedia
2023.05.18編集
キャッシュメモリに用いられる。主メモリよりもさらに高速。
キャッシュメモリは低容量で高価格だがスピードが高速なため、一度アクセスしたデータに何度も繰り返し頻繁にアクセスするための「キャッシュ」として用いられる。
後日注記:SRAMはレジスタと同じくD型フリップフロップで構成されており、高速だが、1ビットに4つのトランジスタが必要なため集積が難しいという特徴がある。
(放送大学「コンピュータの動作と管理 ('17)」を参考に執筆しました。)
Wikipedia
2023.05.18編集
EEPROMは、ROMでありながら高い電圧をかけることで内容を削除し、再び書き込みが可能なメモリ。
EEPROMの一種として構造を簡素化することで高速に書き込みできるフラッシュメモリ(NOR型・NAND型の二種類)があり、USBメモリーやSSDなどに使われている。
(放送大学「コンピュータの動作と管理 ('17)」を参考に執筆しました。)
2023.05.18
メモリの注意点として、電気を消すと記憶した内容が消えてしまう。これを揮発性メモリと呼ぶ。
そのため、電源を消しても保持したいデータは不揮発性のハードディスクなどに保存しなければならない。
(放送大学「コンピュータとソフトウェア ('18)」を参考に執筆しました。)
2023.03.31
徹底攻略 応用情報技術者教科書 平成30年度を参考に執筆しました。
頻繁に読み書きされるデータをキャッシュして効率的にアクセスするために、キャッシュ専用の高速なメモリをCPUと主メモリとの間に配置する方式のことを、キャッシュメモリと呼ぶ。
キャッシュメモリのデータ更新方式には、ライトスルー方式とライトバック方式がある。ライトスルーでは、キャッシュメモリにデータを書き込んだ時点で、同じデータを主メモリにも書き込む。これに対してライトバックでは、すぐに主メモリに書き込まず、後々になって条件が満たされた場合にのみ書き込む。ライトバックのほうがスループレット(処理速度)は向上するが、必ずしもコヒーレンシ(一貫性)は保たれない。
キャッシュメモリの割り当てには、最初に発見した空き領域に配置するファーストヒット方式と、見つかったもののうちベストフィット(そのサイズを満たす最小サイズの領域、すなわち、ちょうどいい大きさの領域)のものを選ぶベストフィット方式がある。
(徹底攻略 応用情報技術者教科書 平成30年度を参考に執筆しました。)
メモリインタリーブは、メモリをメモリバンクと呼ばれる複数のメモリ領域に分割し、それぞれの別のメモリバンクに同時にアクセスできるようにする(ことで効率的にアクセスができる)方式。
(徹底攻略 応用情報技術者教科書 平成30年度を参考に執筆しました。)
キャッシュとは、頻繁にアクセスされるデータを高速な記憶装置に複製することで、高速にアクセスできるようにする機構のこと。
よく使うデータをキャッシュに置き、素早く利用するために使う。
データがハードディスク上にあるよりも、メモリ上にあった方が圧倒的に速いため、よく使うデータをメモリ上に置き、そこからアクセスし、必要になった段階でハードディスクに読み書きするようなキャッシュの実装が考えられる。
(やねうらお氏の「Windowsプロフェッショナルゲームプログラミング」を参考に執筆しました。)
キャッシュは記憶装置だけではなく、ネットワーク通信においても使われる。
Webブラウザが、一度表示したことのある、更新されていないページを再度表示する際に、URLからページをダウンロードせずローカルにあるキャッシュを表示することで、ネットワーク通信をしなくても即座にページが表示される。
もし更新されていた場合は、更新ボタンを押せばURLから再度ダウンロードされる。
このように、メモリやハードディスクあるいはWebブラウザだけではなく、さまざまなところでキャッシュ技術は使われている。
2023.04.03
僕は、プログラミングには二つの大きな点があると思います。それは、「逐次的な処理」と、その中で「データをメモリに保持する」ということです。
プログラムというのは、演算子や入出力関数やサブルーチンやジャンプを行う中で逐次的な処理を行いながら、その中でデータを保持し、さまざまなデータをその逐次的な処理と処理の間でやり取りする、ということです。
基本的に、「流れるフロー」がもしあったとしたら、それはフローだけではなく、その中でやり取りされるデータと一緒に成り立ちます。どこかにデータを記憶することができなければ、フローの中で逐次的な処理と処理が、結果をやり取りすることができません。
なので、CPUとメモリは切り離すことができない不可分の存在です。CPUで逐次的な処理を行い、メモリでデータをやり取りするのです。
使用するメモリ領域の大きさの削減をするために、小さなバッファを使った省メモリの技術が考えられる。
たくさんのデータを扱うプログラムで、すべてのデータを一度にメモリ領域に確保するのではなく、特別なバッファ領域を小さく確保し、データが必要になった時点でそのバッファの中のデータを書き換えることで、全体の使用するメモリ領域を削減できる。
たとえば、全部で1000のデータがあった時、この1000のデータを一度に確保すると、メモリ領域は1000必要になってしまう。
そうではなく、50の小さく特別なデータ領域をバッファとして確保し、必要になったタイミングで、1000のデータの中の必要な部分だけを、50のバッファの中に格納し、別の領域が必要になれば、50のバッファの領域を書き換えることで、全部で50のメモリ領域だけであっても1000の全部のデータを処理することができる。
たとえば、ファイルを読み出す場合、すべてのファイルを一気にメモリに読み込むのではなく、4096バイトの固定長のバッファ領域を使って、4096バイトごとに読み出して処理することが考えられる。どんなにファイルのサイズが大きくても、使用するメモリ領域は4096バイトだけで済む。
応用例としては、Apacheのようなプロセス・スレッドベースのWebサーバに対して、イベント駆動で必要な接続に必要な時にアクセスするNginxのようなWebサーバが挙げられる。一度に全部のスレッドの分だけメモリを確保するのではなく、必要な接続に対して必要なだけのメモリをその都度確保するため、Nginxはメモリの効率がよく、軽量かつ高速であることが知られている。
Linux API(stdio)やNginxも参照のこと。
2023.08.19
Linuxカーネルのメモリ管理(仮想記憶)については、Linuxカーネル(メモリ管理)を参照のこと。
x86アセンブラについては、アセンブリ言語を参照のこと。
Intel CPUについては、Intelを参照のこと。
メモリについての基本は、以下のような書籍が参考になります。