コンピューティングエクスペリエンスの表面レベルを見るのが楽しい場合もあれば、内部の仕組みを詳しく調べるのも楽しい場合もあります。今日は、コンピュータのメモリの構造と、RAMのスティックにどれだけの量を詰め込めるかを見ていきます。
今日の質疑応答セッションは、コミュニティ主導のQ&AWebサイトのグループであるStackExchangeの下位区分であるSuperUserの好意で行われます。
質問
スーパーユーザーリーダーのJohanSmohanは、プロセッサの種類とメモリサイズがどのように連携して、アドレスの総数を生成するかについて取り組んでいます。彼は書く:
32ビットプロセッサと1GBRAMでいくつのメモリアドレスを取得でき、64ビットプロセッサでいくつ取得できますか?
私はそれがこのようなものだと思います:
1 GBのRAMを32ビット4ビット(?)で割って、メモリアドレスの数を取得しますか?
1つのメモリアドレスまたは1つの整数が64ビット幅または8オクテットである64ビットプロセッサと比較して、1つのメモリアドレスが32ビット幅または4オクテット(1オクテット= 8ビット)であることをWikipediaで読みました。しかし、私がそれを正しく理解したかどうかもわかりません。
これらは、好奇心旺盛なオタクを夜に追いやることができる種類の質問です。 Johanの各仮想システムで使用できるアドレスはいくつですか?
答え
スーパーユーザーの寄稿者であるGronostajは、RAMがどのように分割されて利用されているかについての洞察を提供しています。
短い答え: 使用可能なアドレスの数は、次のうち小さい方と同じです。
- バイト単位のメモリサイズ
- CPUのマシンワードに保存できる最大の符号なし整数
上記の長い回答と説明:
メモリはバイト(B)で構成されます。各バイトは8ビットで構成されます(b)。
1 B = 8 b1GBのRAMは実際には1GiB(ギガバイトではなくギビバイト)です。違いは次のとおりです。
1 GB = 10 ^ 9 B = 1 000 000 000 B 1 GiB = 2 ^ 30 B = 1 073 741 824 BCPUマシンワードの大きさに関係なく、メモリのすべてのバイトには独自のアドレスがあります。例えば。 Intel 8086 CPUは16ビットであり、メモリをバイト単位でアドレス指定していたため、最新の32ビットおよび64ビットCPUも同様です。これが最初の制限の原因です。メモリバイトより多くのアドレスを持つことはできません。
メモリアドレスは、CPUがメモリの先頭からスキップして、探しているものに到達するために必要なバイト数です。
- 最初のバイトにアクセスするには、0バイトをスキップする必要があるため、最初のバイトのアドレスは0です。
- 2番目のバイトにアクセスするには、1バイトをスキップする必要があるため、アドレスは1です。
- (など…)
- 最後のバイトにアクセスするために、CPUは1073741823バイトをスキップするため、そのアドレスは1073741823です。
ここで、32ビットが実際に何を意味するのかを知る必要があります。前にも言ったように、それはマシンワードのサイズです。
マシンワードは、CPUが数値を保持するために使用するメモリの量です(RAM、キャッシュ、または内部レジスタに)。 32ビットCPUは、32ビット(4バイト)を使用して数値を保持します。メモリアドレスも数字であるため、32ビットCPUではメモリアドレスは32ビットで構成されます。
これについて考えてみましょう。1ビットの場合、0または1の2つの値を保存できます。さらに1ビットを追加すると、0、1、2、3の4つの値があります。3ビットの場合、8つの値を保存できます。 :0、1、2…6、7。これは実際にはバイナリシステムであり、次のように機能します。
2進化10進数 0 0000 10001 2 0010 3 0011 4 0100 5 0101 6 0110 7 0111 8 1000 9 1001 10 1010 11 1011 121100 131101 141110 15 1111通常の加算とまったく同じように機能しますが、最大桁数は9ではなく1です。10進数の0は
0000、次に1を追加して、0001、もう一度追加すると、0010。ここで起こったことは、小数を持っているようなものです09そして1を追加します:9を0に変更し、次の桁をインクリメントします。上記の例から、一定のビット数の数値に保持できる最大値が常に存在することがわかります。すべてのビットが1で、値を1増やしようとすると、すべてのビットが0になり、数。これは整数オーバーフローと呼ばれ、ユーザーと開発者の両方に多くの不快な問題を引き起こします。
11111111 = 255 + 1 ----------- 100000000 = 0(ここでは9ビットなので、1がトリミングされます)
- 1ビットの場合、最大値は1です。
- 2ビット– 3
- 3ビット– 7
- 4ビット– 15
可能な最大数は常に2 ^ N-1です。ここで、Nはビット数です。前にも言ったように、メモリアドレスは数値であり、最大値もあります。そのため、マシンワードのサイズは、使用可能なメモリアドレスの数の制限でもあります。CPUが、より多くのメモリをアドレス指定するのに十分な大きさの数値を処理できない場合があります。
したがって、32ビットでは0から2 ^ 32-1までの数値を維持でき、それは4 294 967295です。これは1GB RAMの最大アドレスよりも大きいため、特定の場合にはRAMの量が制限要因になります。
32ビットCPUのRAM制限は理論的には4GB(2 ^ 32)であり、64ビットCPUの場合は16 EB(エクサバイト、1 EB = 2 ^ 30 GB)です。言い換えれば、64ビットCPUはインターネット全体をアドレス指定できます…200回;)( ウォルフラムアルファ )。
ただし、実際のオペレーティングシステムでは、32ビットCPUは約3GiBのRAMをアドレス指定できます。これは、オペレーティングシステムの内部アーキテクチャが原因です。一部のアドレスは他の目的のために予約されています。あなたはこのいわゆるについてもっと読むことができます ウィキペディアの3GBの障壁 。この制限を解除するには 物理アドレス拡張 。
メモリアドレス指定について言えば、私が言及しなければならないことがいくつかあります。 仮想メモリ 、 セグメンテーション そして ページング 。
仮想メモリ
@Daniel R Hicksが別の回答で指摘したように、OSは仮想メモリを使用します。つまり、アプリケーションは実際には実際のメモリアドレスではなく、OSによって提供されるアドレスで動作します。
この手法により、オペレーティングシステムは一部のデータをRAMからいわゆるページファイル(Windows)またはスワップ(* NIX)に移動できます。 HDDはRAMよりも数桁遅いですが、めったにアクセスされないデータにとっては深刻な問題ではなく、OSが実際にインストールしたよりも多くのRAMをアプリケーションに提供できるようにします。
ページング
これまで話していたのは、フラットアドレッシングスキームと呼ばれるものです。
ページングは、フラットモデルの1つのマシンワードで通常可能であるより多くのメモリをアドレス指定できるようにする代替のアドレス指定スキームです。
4文字の単語でいっぱいの本を想像してみてください。各ページに1024個の数字があるとしましょう。番号に対処するには、次の2つのことを知っておく必要があります。
- その単語が印刷されているページの数。
- そのページのどの単語があなたが探しているものです。
これがまさに最新のx86CPUがメモリを処理する方法です。 4 KiBページ(それぞれ1024マシンワード)に分割されており、それらのページには番号が付いています。 (実際には、ページは4MiBの大きさまたは2MiBの大きさである可能性があります PAE )。メモリセルをアドレス指定する場合は、そのページのページ番号とアドレスが必要です。各メモリセルは正確に1組の数値で参照されることに注意してください。これは、セグメンテーションには当てはまりません。
セグメンテーション
まあ、これはページングに非常に似ています。一例を挙げると、Intel8086で使用されていました。アドレスのグループは、ページではなくメモリセグメントと呼ばれるようになりました。違いは、セグメントがオーバーラップする可能性があり、それらは多くオーバーラップすることです。たとえば、8086では、ほとんどのメモリセルが4096の異なるセグメントから利用可能でした。
例:
8バイトのメモリがあり、255に等しい4番目のバイトを除いてすべてゼロを保持しているとしましょう。
フラットメモリモデルの図:
_____ | 0 | | 0 | | 0 | | 255 | | 0 | | 0 | | 0 | | 0 | ーーーーーページメモリのイラスト 4バイトページの場合:
PAGE0 _____ | 0 | | 0 | | 0 |ページ1 | 255 | _____ ----- | 0 | | 0 | | 0 | | 0 | -----セグメント化されたメモリの図 4バイトのセグメントが1シフトされています。
SEG 0 _____ SEG 1 | 0 | _____ SEG 2 | 0 | | 0 | _____ SEG 3 | 0 | | 0 | | 0 | _____ SEG 4 | 255 | | 255 | | 255 | | 255 | _____ SEG 5 ----- | 0 | | 0 | | 0 | | 0 | _____ SEG 6 ----- | 0 | | 0 | | 0 | | 0 | _____ SEG 7 ----- | 0 | | 0 | | 0 | | 0 | _____ ----- | 0 | | 0 | | 0 | | 0 | ----- ----- ----- -----ご覧のとおり、4番目のバイトは次の4つの方法でアドレス指定できます。(0からのアドレス指定)
- セグメント0、オフセット3
- セグメント1、オフセット2
- セグメント2、オフセット1
- セグメント3、オフセット0
常に同じメモリセルです。
実際の実装では、セグメントは1バイト以上シフトされます(8086の場合は16バイトでした)。
セグメンテーションの悪い点は、複雑なことです(ただし、すでにご存知だと思います;)良い点は、いくつかの巧妙な手法を使用してモジュラープログラムを作成できることです。
たとえば、あるモジュールをセグメントにロードしてから、セグメントが実際よりも小さい(モジュールを保持するのに十分小さい)ふりをして、その疑似小さいセグメントとオーバーラップしない最初のセグメントを選択して、次にロードすることができます。モジュールなど。基本的に、この方法で取得できるのは、可変サイズのページです。
説明に追加するものがありますか?コメントで音を立ててください。他の技術に精通したStackExchangeユーザーからの回答をもっと読みたいですか? ここで完全なディスカッションスレッドをチェックしてください 。